密碼

【問題描述】

  假髮通過了不懈的努力,得到了將軍家門鎖的密碼(一串小寫英文字母)。但是假髮被十四和猩猩他們盯上了,所以假髮需要把密碼傳遞出去。因爲假髮不想十四他們發現幾鬆門前貼的小紙條就是將軍家的密碼,所以他加密了密碼(新八:聽起來有點詭異)。加密方法如下:隨機地,在密碼中任意位置插入隨機長度的小寫字符串。

  不過,假髮相信銀桑和他那麼多年小學同學,一定能猜中密碼是什麼的(新八:銀桑什麼時候成攮夷志士了!!!)。可是,寫完了小紙條之後,假髮覺得有點長,就想截去頭和尾各一段(可以爲空),讓剩下的中間那一段依然包含真~密碼。想着想着,假髮就想知道有多少種可行方案。結果在沉迷於稿紙之際,假髮被投進了獄門島(新八:……)。於是,就由你計算了。

【輸入格式】

  兩行非空字符串,純小寫英文字母,第一行是加密後的密碼,第二行是原密碼。第一行長度不超過 300000,第二行不超過 200。

【輸出格式】

  一行,有多少種方案。注意:不剪也是一種方案。

【輸入樣例】

【樣例1】
 abcabcabc
 cba

【樣例2】
 abcabcaba
 cba

【樣例3】
 abcabcabac
 cba

【輸出樣例】

【樣例1】
 9

【樣例2】
 12

【樣例3】
 18

【樣例解釋】

【樣例1解釋】
  用(L,R)表示一種方案,其中L和R分別表示截去頭和尾的長度。這9種方案分別是 (0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2,0),(2,1),(2,2)。

【數據範圍】

30%的數據滿足第一行長度不超過1000。
100%的數據滿足第一行長度不超過300000,方案總數不超過10^18。

首先從加密字符串中尋找密碼的開頭字符,存儲此時開頭字母下標w,更新之前出現過密碼的開頭字符的下標q,然後依次往後找密碼的其他字符,直到找到末尾字符,此時計算方案數ans+=(w-p)*(n+1-i)。因爲隨着不斷的尋找,有多個密碼出現時肯定會出現重複計算的問題,所以記錄開頭字母下標可以避免重複計算。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
long long ans=0;
char ch[300005],cmd[205];

int main()
{
    //freopen("password.in","r",stdin);
    //freopen("password.out","w",stdout);

    scanf("%s",ch);
    scanf("%s",cmd);
    int n=strlen(ch)-1;
    int m=strlen(cmd)-1;
    int s=0,t=n,p=0,w=-1;
    int i=0,j=0;
    while(i<=n)
    {
        while(i<=n&&ch[i]!=cmd[j]) i++;
        if(i>n) break;
        if(j==0) p=w,w=i;
        if(j==m) ans+=(w-p)*(n+1-i);
        i++,j++;
        if(j>m) j=0,i=w+1;
    }
    printf("%I64d",ans);
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章