Birthday Cake
思路:找到每个串的公共前后缀,统计公共前后缀之间的字符串的hash值,并判断所给n个串中是否存在符合条件的串
eg:abbddab
对于该串,我们不难发现,公共前后缀是ab,公共前后缀之间的串是bdd,我们需要统计所有串中bdd出现的次数
注意,求得不是最长公共前后缀,而是所有的公共前后缀
细节问题:1、取模
2、RE可能是因为tmp定义为string,每次对tmp赋值的时候,tmp串会进行依次刷新,会造成堆栈溢出
#include<bits/stdc++.h>
#define ll long long
#define mp make_pair
using namespace std;
const int N = 4e5 + 10;
const ll m1 = 1e9 + 7;
const ll m2 = 1e9 + 9;
const int mod1 = 233;
const int mod2 = 19;
string st[N];
char tmp[N];
ll n, ans;
ll num1[N], num2[N], hash1[N], hash2[N];
map<pair<ll,ll>, int> cnt;
//每个串,只需要考虑长度小于等于该串的长度的串
bool cmp(string st1, string st2){
if(st1.size() < st2.size()) return true;
return false;
}
void init(){
num1[0] = num2[0] = 1;
for(int i = 1; i < N - 1; i++){
num1[i] = num1[i - 1] * mod1 % m1;
num2[i] = num2[i - 1] * mod2 % m2;
}
}
ll gethash1(int l, int r){
if(l > r) return 0;
return (hash1[r] - (hash1[l - 1] * num1[r - l + 1]) % m1 + m1)%m1;
}
ll gethash2(int l, int r){
if(l > r) return 0;
return (hash2[r] - (hash2[l - 1] * num2[r - l + 1]) % m2 + m2) % m2;
}
signed main(){
cin >> n;
for(int i = 1; i <= n; i++){
cin >> st[i];
}
init();
sort(st + 1, st + 1 + n, cmp);
for(int i = 1; i <= n; i++){
int len = st[i].size();
for(int j = 0; j < len; j++){
tmp[j + 1] = st[i][j];
}
for(int j = 1; j <= len; j++){
hash1[j] = (hash1[j - 1] * mod1 % m1 + (tmp[j] - 'a') + 122)%m1;
hash2[j] = (hash2[j - 1] * mod2 % m2 + (tmp[j] - 'a') + 122) % m2;
}
for(int j = 1; j <= len - j + 1; j++){
int t = len - j + 1;
if(gethash1(1,j) == gethash1(t,len) && gethash2(1,j) == gethash2(t, len)){
ans += cnt[mp(gethash1(j + 1, t - 1), gethash2(j + 1, t - 1))];
}
}
ans += cnt[mp(gethash1(1, len), gethash2(1, len))];
cnt[mp(gethash1(1, len), gethash2(1, len))]++;
}
cout << ans;
return 0;
}