HDOJ 5343 MZL's Circle Zhou 后缀自动机


HDOJ 5343 MZL's Circle Zhou 后缀自动机_第1张图片


对第二个串建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 .
 

Input
The first line of the input is a single integer  T (T5) , 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 .
 

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
2015 Multi-University Training Contest 5
 

/* ***********************************************
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;
}





你可能感兴趣的:(HDOJ 5343 MZL's Circle Zhou 后缀自动机)