给你一个串,问你他的所有前缀子串在本串中的出现次数,注释:abc的前缀子串是
a ab abc;
思路:
还是利用了next数组,先对子串求出next数组,再开一个数组dp,初始化全是1,因为每个以当前i结尾的都至少是1,然后从后往前更新,把以i结尾的加到以next[i]结尾的上,
运用的next数组的特点相当于 123123123 最后一个3加到倒数第二个3,倒数第二个3再加到第一个3 那么以3结尾的(123)出现了三次,以3结尾的(123123)出现了两次,以3结尾的(123123123) 出现了一次。
例子详细数据:
原串 123123123
next 000123456
dp 333222111
提示:
这个题目的串之间是可以交叉的,但不可以完全重叠,比如对与这个题目11111的答案是15.
#include<stdio.h> #include<string.h> #define N 200000 + 100 char str[N]; int next[N]; int dp[N]; void get_next(int m) { int j ,k; j = 0 ,k = -1; next[0] = -1; while(j < m) { if(k == -1 || str[j] == str[k]) next[++j] = ++k; else k = next[k]; } return ; } int main () { int t ,m ,i; scanf("%d" ,&t); while(t--) { scanf("%d" ,&m); scanf("%s" ,str); get_next(m); for(i = 1 ;i <= m ;i ++) dp[i] = 1; int sum = 0; for(i = m ;i >= 1 ;i --) { if(next[i]) { dp[next[i]] += dp[i]; dp[next[i]] %= 10007; } sum += dp[i]; sum %= 10007; } /* for(i = 1 ;i <= m ;i ++) printf("%d " ,next[i]); printf(" "); for(i = 1 ;i <= m ;i ++) printf("%d " ,dp[i]); printf(" "); */ printf("%d " ,sum); } return 0; }