description
analysis
-
考慮的某個前綴和的某個前綴拼成的一個字符串
-
如果該字符串可以被另幾種拼出來,欽定最短的那種只算一次
-
考慮,其中最短
-
其中滿足同時是的前綴和後綴,可以畫圖理解
-
這是因爲每個都是的前綴,且也完全是的後綴
-
相當於求得的的定義,的總指向的末尾位置
-
對於的前綴,只要該前綴有,說明這種前綴可以被它指向的的更短前綴替代
-
當然前綴還可以被它自己的不斷替代,直到該前綴沒有,即不可被替代
-
建出的後,拿在上面跑,求出每個前綴在中出現的次數
-
具體求就是匹配完把求一次後綴和,相當於所有情況全部集中到沒有的前綴上,就求出了每個前綴出現次數
-
然後把答案減掉前綴出現的次數就好了
-
這題思維難但代碼很短,以後要好好動腦想
code
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 100005
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
using namespace std;
ll next[MAXN],num[MAXN];
char s[MAXN],t[MAXN];
ll n,m,ans;
int main()
{
//freopen("T2.in","r",stdin);
freopen("password.in","r",stdin);
freopen("password.out","w",stdout);
scanf("%s%s",s+1,t+1),n=strlen(s+1),m=strlen(t+1),ans=n*m;
for (reg i=2,j=0;i<=m;++i)
{
while (j && t[j+1]!=t[i])j=next[j];
if (t[j+1]==t[i])++j;next[i]=j;
}
for (reg i=2,j=0;i<=n;++i)
{
while (j && t[j+1]!=s[i])j=next[j];
if (t[j+1]==s[i])
{
++num[++j];
if (j==m)j=next[j];
}
}
fd(i,n,1)num[next[i]]+=num[i];
fo(i,1,m)ans-=next[i]?num[i-next[i]]:0;
printf("%lld\n",ans);
return 0;
}