A Secret(KMP)

A Secret

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others)
Total Submission(s): 830    Accepted Submission(s): 323


Problem Description

Today is the birthday of SF,so VS gives two strings S1,S2 to SF as a present,which have a big secret.SF is interested in this secret and ask VS how to get it.There are the things that VS tell:
  Suffix(S2,i) = S2[i...len].Ni is the times that Suffix(S2,i) occurs in S1 and Li is the length of Suffix(S2,i).Then the secret is the sum of the product of Ni and Li.
  Now SF wants you to help him find the secret.The answer may be very large, so the answer should mod 1000000007.

 

Input

Input contains multiple cases.
  The first line contains an integer T,the number of cases.Then following T cases.
  Each test case contains two lines.The first line contains a string S1.The second line contains a string S2.
  1<=T<=10.1<=|S1|,|S2|<=1e6.S1 and S2 only consist of lowercase ,uppercase letter.

 

Output

For each test case,output a single line containing a integer,the answer of test case.
  The answer may be very large, so the answer should mod 1e9+7.

 

Sample Input

2
aaaaa
aa
abababab
aba

Sample Output

13 19
Hint
case 2:
Suffix(S2,1) = "aba",
Suffix(S2,2) = "ba",
Suffix(S2,3) = "a".
N1 = 3,
N2 = 3,
N3 = 4.
L1 = 3,
L2 = 2,
L3 = 1.
ans = (3*3+3*2+4*1)%1000000007.

 

Source

2017中国大学生程序设计竞赛 - 网络选拔赛

 

//题意,一个S串,一个T串,问T的每一个后缀串在S串的匹配次数乘后缀串长度之和为多少。

//题解:S,T串逆序后,跑一遍kmp,并且统计匹配度的次数,然后,从lent向前推,因为在匹配时,没有累计T串中T串自己的可匹配情况,

例如逆序后, S: aba T: aba

kmp后,num : 1 1 1 (长为1的匹配数,长为2的匹配数,长为3的匹配数)

而实际,num: 2 1 1 ,因为 aba 匹配成功后,还包含了一次 a 的匹配

所以,最后还要逆序跑一下,利用fail(next)数组来加上,即为答案

 1 # include <cstdio>
 2 # include <cstring>
 3 # include <cstdlib>
 4 # include <iostream>
 5 # include <vector>
 6 # include <queue>
 7 # include <stack>
 8 # include <map>
 9 # include <bitset>
10 # include <sstream>
11 # include <set>
12 # include <cmath>
13 # include <algorithm>
14 # pragma  comment(linker,"/STACK:102400000,102400000")
15 using namespace std;
16 # define LL          long long
17 # define pr          pair
18 # define mkp         make_pair
19 # define lowbit(x)   ((x)&(-x))
20 # define PI          acos(-1.0)
21 # define INF         0x3f3f3f3f3f3f3f3f
22 # define eps         1e-8
23 # define MOD         1000000007
24 
25 inline int scan() {
26     int x=0,f=1; char ch=getchar();
27     while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
28     while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
29     return x*f;
30 }
31 inline void Out(int a) {
32     if(a<0) {putchar('-'); a=-a;}
33     if(a>=10) Out(a/10);
34     putchar(a%10+'0');
35 }
36 #define MX 1000050
37 /**************************/
38 int lens,lent;
39 char S[MX];
40 char T[MX];
41 int num[MX];
42 int fail[MX];
43 
44 void get_next(char * t)
45 {
46     int i=0,j=-1;
47     fail[0]=-1;
48     while(i<lent)
49     {
50         if (j==-1||T[i]==T[j])
51             fail[++i]=++j;
52         else
53             j=fail[j];  //回溯
54     }
55 }
56 
57 void KMP(char *s,char *t)
58 {
59     memset(num,0,sizeof(num));
60     get_next(t);
61     int i=0,j=0;
62     while (i<lens)
63     {
64         if (j==-1||S[i]==T[j])
65         {
66             i++,j++;
67         }
68         else j = fail[j];
69 
70         if (j!=-1) num[j]++;
71 
72         if (j==lent) j = fail[j];
73     }
74 }
75 
76 int main()
77 {
78     int cas = scan();
79     while (cas--)
80     {
81         scanf("%s",S);
82         scanf("%s",T);
83         lens = strlen(S);
84         lent = strlen(T);
85         reverse(S,S+lens);
86         reverse(T,T+lent);
87         KMP(S,T);
88         LL ans = 0;
89         for (int i=lent;i>0;i--)
90         {
91             num[fail[i]]+=num[i];
92             ans = (ans + ((LL)i*num[i])%MOD)%MOD;
93         }
94         printf("%lld
",ans);
95     }
96     return 0;
97 }
View Code
原文地址:https://www.cnblogs.com/haoabcd2010/p/7399298.html