对第二个串建SAM求出第二个串的以每个字符开头的不同子串的数目..
再对第一个串建SAM,遍历自动机如果某个节点后面没有某个字符则答案加上这个节点的出现次数乘上以这个字符为开头的在第二个串中的不同子串的数目..
MZL's Circle Zhou
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 244 Accepted Submission(s): 84
Problem Description
MZL's Circle Zhou is good at solving some counting problems. One day, he comes up with a counting problem:
You are given two strings a,b which consist of only lowercase English letters. You can subtract a substring x (maybe empty) from string a and a substring y (also maybe empty) from string b , and then connect them as x+y with x at the front and y at the back. In this way, a series of new strings can be obtained.
The question is how many different new strings can be obtained in this way.
Two strings are different, if and only if they have different lengths or there exists an integer i such that the two strings have different characters at position i .
You are given two strings a,b which consist of only lowercase English letters. You can subtract a substring x (maybe empty) from string a and a substring y (also maybe empty) from string b , and then connect them as x+y with x at the front and y at the back. In this way, a series of new strings can be obtained.
The question is how many different new strings can be obtained in this way.
Two strings are different, if and only if they have different lengths or there exists an integer i such that the two strings have different characters at position i .
Input
The first line of the input is a single integer
T (T≤5)
, indicating the number of testcases.
For each test case, there are two lines, the first line is string a , and the second line is string b . 1<=|a|,|b|<=90000 .
For each test case, there are two lines, the first line is string a , and the second line is string b . 1<=|a|,|b|<=90000 .
Output
For each test case, output one line, a single integer indicating the answer.
Sample Input
2 acbcc cccabc bbbabbababbababbaaaabbbbabbaaaabaabbabbabbbaaabaab abbaabbabbaaaabbbaababbabbabababaaaaabbaabbaabbaab
Sample Output
135 557539
Author
SXYZ
Source
/* ***********************************************
Author :CKboss
Created Time :2015年08月26日 星期三 18时49分03秒
File Name :HDOJ5343.cpp
************************************************ */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef unsigned long long int LL;
const int CHAR=26,maxn=200100;
struct SAM_Node
{
SAM_Node *fa,*next[CHAR];
int len,id,pos;
SAM_Node(){}
SAM_Node(int _len)
{
fa=0; len=_len;
memset(next,0,sizeof(next));
}
};
SAM_Node SAM_node[maxn],*SAM_root,*SAM_last;
int SAM_size;
SAM_Node *newSAM_Node(int len)
{
SAM_node[SAM_size]=SAM_Node(len);
SAM_node[SAM_size].id=SAM_size;
return &SAM_node[SAM_size++];
}
SAM_Node *newSAM_Node(SAM_Node *p)
{
SAM_node[SAM_size]=*p;
SAM_node[SAM_size].id=SAM_size;
return &SAM_node[SAM_size++];
}
void SAM_init()
{
SAM_size=1;
SAM_root=SAM_last=newSAM_Node(0);
SAM_node[0].pos=0;
}
void SAM_add(int x,int len)
{
SAM_Node *p=SAM_last,*np=newSAM_Node(p->len+1);
np->pos=len; SAM_last=np;
for(;p&&!p->next[x];p=p->fa)
p->next[x]=np;
if(!p)
{
np->fa=SAM_root; return ;
}
SAM_Node *q=p->next[x];
if(q->len==p->len+1)
{
np->fa=q; return ;
}
SAM_Node *nq=newSAM_Node(q);
nq->len=p->len+1;
q->fa=nq; np->fa=nq;
for(;p&&p->next[x]==q;p=p->fa)
p->next[x]=nq;
}
int c[maxn],num[maxn];
SAM_Node* top[maxn];
void Count(char str[],int len)
{
memset(c,0,sizeof(c));
memset(num,0,sizeof(num));
for(int i=0;i<SAM_size;i++) c[SAM_node[i].len]++;
for(int i=1;i<=len;i++) c[i]+=c[i-1];
for(int i=0;i<SAM_size;i++) top[--c[SAM_node[i].len]]=&SAM_node[i];
SAM_Node *p=SAM_root;
for(;p->len!=len;p=p->next[str[p->len]-'a']) num[p->id]=1;
num[p->id]=1;
for(int i=SAM_size-1;i>=0;i--)
{
p=top[i];
if(p->fa)
{
SAM_Node *q=p->fa; num[q->id]+=num[p->id];
}
}
}
int len1,len2;
char str1[maxn],str2[maxn];
LL cum[maxn];
bool vis[maxn];
int dfs(int u)
{
if(vis[u]) return num[u];
vis[u]=true;
int ret=1;
for(int i=0;i<26;i++)
{
if(SAM_node[u].next[i])
{
ret+=dfs(SAM_node[u].next[i]->id);
}
}
return num[u]=ret;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T_T;
scanf("%d",&T_T);
while(T_T--)
{
cin>>str1>>str2;
len1=strlen(str1); len2=strlen(str2);
SAM_init();
for(int i=0;i<len2;i++)
SAM_add(str2[i]-'a',i);
memset(cum,0,sizeof(cum));
memset(vis,false,sizeof(vis));
dfs(1);
LL ans=0;
for(int i=0;i<26;i++)
{
if(SAM_node[1].next[i])
{
cum[i]=num[SAM_node[1].next[i]->id];
}
}
SAM_init();
for(int i=0;i<len1;i++) SAM_add(str1[i]-'a',i);
for(int i=2;i<SAM_size;i++)
{
if(SAM_node[i].fa)
{
LL l=SAM_node[i].len-SAM_node[i].fa->len;
for(int j=0;j<26;j++)
{
if(SAM_node[i].next[j]==0) ans+=l*cum[j];
}
ans+=l;
}
}
cout<<ans+1<<endl;
}
return 0;
}