hdu 3336

<span style="background-color: rgb(0, 153, 0);">/*題意:就是讓給你一個字符串,然後計算不斷增加的前綴字符串在整個字符創當中出現的次數和,可能出現的次數過大,所以要求結果1007.
例如:abab a 2 ab 2 aba 1 abab 1  2+2+1+1=6
*/
/*思路:其實我們想想比如對於位置i來說,現在我們求出了f[i]的值,那麼[0,f[i]-1]串就是一個
能匹配i-1位置的最長的前綴串。且我們根據f[i]的值可以定位其他所有可匹配的前綴。KMP的思想
就是找出每個位置i的可匹配最大前綴j。令dp[i]表示S[0,i-1]串的後綴能匹配的前綴個數,
那麼dp[i]=dp[next[i]]+1, dp[1]=1正好表示串s[0]的後綴只能匹配串s[0].
*/</span>


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pp;
#define inf 0x3f3f3f3f
#define eps 1e-10
#define maxl 200020
#define mem(i,j) memset(i,j,sizeof(i))
const int mod=10007;
int f[maxl],d[maxl],len;
char s[maxl];
void getnext(char *s,int *f){
    f[0]=f[1]=0;
    for(int i=1;i<len;i++){
        int j=f[i];
        while(j&&s[i]!=s[j]) j=f[j];//這裏不斷的替換來降低複雜度
        f[i+1]=(s[i]==s[j])?j+1:0;//f[i+1]保存的是s[i]的前綴的長度
    }
}

int main()
{
  //freopen("in.txt", "r", stdin);
    int t;
    cin>>t;
    while(t--){
        cin>>len>>s;
        getnext(s,f);
        memset(d,0,sizeof(d));
        int ans=0;
        for(int i=1;i<=len;i++){
            d[i]=d[f[i]]+1;//因爲f[i]記錄的是i-1的前綴的長度 但是不知道它的次數 後面的是在前面的結果上面累加的 所以每次加1 直到後面如果還是有相同的前綴的時候已經累加上去了
            ans=(ans+d[i])%mod;
        }
        cout<<ans<<endl;
    }
}

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