string string string
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1905 Accepted Submission(s): 567
Problem Description
Uncle Mao is a wonderful ACMER. One day he met an easy problem, but Uncle Mao was so lazy that he left the problem to you. I hope you can give him a solution.
Given a string s, we define a substring that happens exactly k times as an important string, and you need to find out how many substrings which are important strings.
Given a string s, we define a substring that happens exactly k times as an important string, and you need to find out how many substrings which are important strings.
Input
The first line contains an integer
T
(
T≤100
) implying the number of test cases.
For each test case, there are two lines:
the first line contains an integer k ( k≥1 ) which is described above;
the second line contain a string s ( length(s)≤105 ).
It's guaranteed that ∑length(s)≤2∗106 .
For each test case, there are two lines:
the first line contains an integer k ( k≥1 ) which is described above;
the second line contain a string s ( length(s)≤105 ).
It's guaranteed that ∑length(s)≤2∗106 .
Output
For each test case, print the number of the important substrings in a line.
Sample Input
2 2 abcabc 3 abcabcabcabc
Sample Output
6 9
这就是hdu 4641差不多的一个原题,不知道sam除了相同字符串还有什么重要作用。。
#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
using namespace std;
typedef long long LL;
const int maxn = 2*1e6 + 8;
string s;
int k;
struct SAM
{
int ch[maxn][26],pre[maxn],val[maxn],endpos[maxn];
//val[]当前位置串的长度。一般是根据这个串的长度做文章。
//diy
int num[maxn],num1[maxn];
//diy
int last, tot;
void init(){
last = tot = 0;
memset(ch[0], -1, sizeof ch[0]);
pre[0] = -1; val[0] = 0;
}
int extend(int c, int ind){
int p = last, np = ++tot;
//diy
num[np]=0;
num1[np]=0;
//diy
val[np] = val[p] + 1; endpos[np] = ind;
memset(ch[np], -1, sizeof ch[np]);
while(~p && ch[p][c] == -1) ch[p][c] = np, p = pre[p];
if(p == -1) pre[np] = 0;
else{
int q = ch[p][c];
if(val[q] != val[p] + 1){
int nq = ++tot;
num[nq]=num[q];
num1[nq]=num1[q];
memcpy(ch[nq], ch[q], sizeof ch[q]);
val[nq] = val[p] + 1;
pre[nq] = pre[q];
pre[q] = pre[np] = nq;
while(~p && ch[p][c] == q) ch[p][c] = nq, p = pre[p];
}
else pre[np] = q;
}
last = np;
//diy
int ans=0;
int f,f1;
f=f1=1;
while(np!=-1&&(f||f1))
{
num[np]++;num1[np]++;
if(num[np]==k&&f==1)
ans+=val[np]-val[pre[np]],f=0;
if(num1[np]==k+1&&f1==1)
ans-=val[np]-val[pre[np]],f1=0;
np=pre[np];
}
//diy
// return val[np] - val[pre[np]];
return ans;
}
}sam;
int main()
{
int n, i,t;
scanf("%d",&t);
while(t--)
{
LL sum =0;
scanf("%d",&k);
cin >> s;
n = s.size();
sam.init();
for(i = 0; i < n; i++) sum += sam.extend(s[i] - 'a', i+1);
cout << sum << endl;
}
return 0;
}