1. 程式人生 > >3336 (Next陣列+dp)

3336 (Next陣列+dp)

Count the stringHDU - 3336 

題意:給定字串s,求s的所有字首作為子串在s中出現的次數和。

思路:考慮dp

dp[i] 表示以第i個字母結尾的所有後綴與s的字首的匹配次數。

按照最暴力的想法來做的話,肯定我得列舉以第i個字母結尾的每個字尾。

其實也可以這樣想:dp[i] 等於s(0,i)最長字尾對結果的貢獻加1。然後又kmp裡Next陣列可以得知,s(0,i)的最長字尾等於Next[i]對應的s的字首。

由此可得:dp[i] = dp[Next[i]]+1;  dp[0] = 0;

吐槽:此題資料太水。。。

#include <bits/stdc++.h>
using namespace std;
const int mod = 10007;
char s[2000005];
int dp[2000005],Next[2000005];
void getNext(char s[])
{
    int len = strlen(s),i = 0;
    int k = -1;
    Next[0] = -1;
    while(i < len)
    {
        if(k == -1 || s[i] == s[k])
        {
            Next[++i] = ++k;
        }
        else k = Next[k];
    }
}
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        int n;
        scanf("%d",&n);
        scanf("%s",s);
        getNext(s);
        dp[0] = 0;
        int ans = 0;
        for(int i = 1; i <= n; i++)
        {
            dp[i] = dp[Next[i]]+1;
            dp[i] %= mod;
            ans += dp[i];
            ans %= mod;
        }
        printf("%d\n",ans);
    }
    return 0;
}