题意求字符串的每个后缀与原串的最长公共前缀之和。
需要注意的就是题目准确问的是按照文中所给的代码执行需要判断几次,如果最长公共前缀等于该后缀的长度,则会判断Next[i]次(Next[i]为以i为开始的后缀与原串的最长公共前缀)。如果不等,则会判断Next[i]+1次,因为会判断一次失配。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const ll maxn=1000010;
int next_s[maxn];
int len,t;
ll ans;
char s[maxn];
void getnext(){
next_s[0]=len;
int k=0;
while(k+1<len&&s[k]==s[k+1]){
++k;
}
next_s[1]=k;
int po=1;
for(int i=2;i<len;i++){
if(i+next_s[i-po]<po+next_s[po]){
next_s[i]=next_s[i-po];
}
else {
int j=po+next_s[po]-i;
if(j<0)j=0;
while(i+j<len&&s[i+j]==s[j]){
++j;
} //next_s数组的赋值必须在while循环外边因为有可能不进循环
next_s[i]=j;
po=i;
}
}
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%s",s);
len=strlen(s);
ans=0;
getnext();
for(int i=1;i<len;i++){
if(next_s[i]==len-i)ans+=next_s[i];
else ans+=(next_s[i]+1);//如果不等于len-i说明多了失配的一步
}
cout<<ans<<endl;
}
return 0;
}
// /\ | / |**、
// / \ | / | \
// / \ |/ | / _____ ____ | /
// /------\ |\ |__/ / \ \ /\ / / \ | /
// / \ | \ | / \ \ / \ / /______\ |/
// / \ | \ | \ / \ / \ / \ |
// / \ | \ | \_____/ \/ \/ \_____ |
/**
* ┏┓ ┏┓
* ┏┛┗━━━━━━━┛┗━━━┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*/
// warm heart, wagging tail,and a smile just for you!
//
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// .' \| |// `.
// / \||| : |||// \
// / _||||| -:- |||||- \
// | | \\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//