题目链接:A Secret
题目大意:给你两个字符串,然后需要你对模式串的后缀去对原串匹配,原串后缀长度为1的出现多少次贡献就是1*n,长度为2的贡献就是2*n,然后要求你算出这个总贡献mod(1e9+7)
题目思路:既然要求的是后缀匹配,那么我们将两个串都翻转过来进行正着匹配就好了,然后我们需要去在KMP里面去算,当KMP匹配到失配的时候那么我们可以知道这时的j就是我们已经匹配成功的串,那么这个串的贡献是多少呢?自然是j*(j+1)/2,因为匹配了j个字符,那么j-1、j-2、…、1个字符肯定都在这之前已经匹配到了,还需要注意的一个问题是,最后失配的情况,可能一直到最后都不会失配,所以我们让其失配,然后就做一下处理就好了,这题因为j*(j+1)/2是整数,所以不需要用逆元去算,直接暴力去算就好了
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
const int mod = 1e9+7;
ll n,Next[maxn],ret;
char mo[maxn],str[maxn],ans[maxn];
void getNext(){
ll i = 0,j = -1,len = strlen(mo);
while(i < len){
if(j == -1||mo[i] == mo[j]) Next[++i] = ++j;
else j = Next[j];
}
}
void kmp(){
ll i = 0,j = 0,len1 = strlen(mo),len2 = strlen(str);
ll ans = 0;
while(i < len2){
if(j == -1||mo[j] == str[i]){
j++;
i++;
}
else ret = (ret+((j+1)*j)/2)%mod,j = Next[j];
}
while(j != -1){
ret = (ret+((j+1)*j)/2)%mod;
j = Next[j];
}
printf("%lld\n",ret);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
ret = 0ll;
scanf("%s%s",str,mo);
reverse(str,str+strlen(str));
reverse(mo,mo+strlen(mo));
memset(Next,-1,sizeof(Next));
getNext();
kmp();
}
return 0;
}
Uupdate:这个KMP写法有问题,有一组数据str:baabaa
mo:caabaa过不去,所以需要使用正确的姿势:
#include <bits/stdc++.h>
using namespace std;
const int N = 1000005;
const int Q = 1e9 + 7;
char s[N] , t[N];
int n , m , f[N] , cnt[N];
void work() {
scanf("%s%s" , t , s);
n = strlen(t);
m = strlen(s);
reverse(s , s + m);
reverse(t , t + n);
f[0] = f[1] = 0;
for (int i = 1 ; i < m ; ++ i) {
int j = f[i];
while (j && s[i] != s[j])
j = f[j];
f[i + 1] = s[i] == s[j] ? j + 1 : 0;
}
memset(cnt , 0 , sizeof(int) * (m + 1));
for (int i = 0 , j = 0 ; i < n ; ++ i) {
while (j && t[i] != s[j])
j = f[j];
j += (t[i] == s[j]);
++ cnt[j];
}
for (int i = m ; i > 0 ; -- i) {
cnt[f[i]] += cnt[i];
}
int res = 0;
for (int i = 1 ; i <= m ; ++ i) {
res += (long long)cnt[i] * i % Q;
res %= Q;
}
cout << res << endl;
}
int main() {
int T;
scanf("%d" , &T);
while (T --) {
work();
}
}