POJ - 3415 Common Substrings (suffix array stack monotone +)

Topic links: Click here

Title effect: given two strings, and then gives a k, Q two string length k greater than or equal to the number of common substring (reusable type)

Topic Analysis: Because it involves the substring problem, first ran with the suffix array to array height, the next two strings if direct enumeration height of each location to count the answer, time complexity is n * n, or not completed within a predetermined period of time, of course, to mention a practice mouth n * n here, the value of the first pre-nlogn height of any two suffixes, and then directly enumerate all suffixes n * n two strings if its height greater than equal to k, the contributions to the height-k + 1, is obviously will timeout

Then we can start from the nature of the height of the array, because of the length limit k, so the height array can be divided into several independent groups, each group to ensure that the minimum height is greater than or equal k's, which for now height to meet the conditions of a group, because the longest common prefix sa any two positions represented by the suffix, which is the minimum value in the range of height, so that we can contribute for the a string statistics, when the case of when the string B, will contribute breath gave him, of course, the maintenance of the contribution of a string of a, we need to calculate the contribution of real-time based on the current minimum height, here I did not think, read explanations of others after suddenly realized that here with a monotonous stack can be easily solved, monotonous stack role here is to record the a section on certain period there have been a few times, we need to maintain a large stack top, which is to maintain a monotonically increasing sequence, when faced with a number smaller than the top of the stack when it is necessary to stack eleven in the stack than the current large number of elements, its contribution to clear Recalculated, because the calculation of the contribution unified use: height-k + 1 this formula to calculate, before the larger elements in the stack after use this formula to calculate, because now experiencing smaller than its elements, so apparently previously calculated results count more than a part, need to lose excess of these contributions, and thus contribute to the maintenance monotone stack

Of course, after a string A complete stats Contribution to remember also B string statistical contribution again, because in the process after the first A B A and B will be the first two cases

Code:

#include<iostream>
#include<cstdio> 
#include<string>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;

typedef long long LL;

const int inf=0x3f3f3f3f;

const int N=2e5+100;

vector<int>ans;

char str[N];

int Stack[N],cnt[N];

int sa[N]; //SA数组,表示将S的n个后缀从小到大排序后把排好序的
//的后缀的开头位置顺次放入SA中
int t1[N],t2[N],c[N];

int rk[N],height[N],belong[N],len,k,mark;

int s[N];

bool vis[110];
 
void build_sa(int s[],int n,int m)//n为添加0后的总长
{
    int i,j,p,*x=t1,*y=t2;
    for(i=0;i<m;i++) 
		c[i]=0;
    for(i=0;i<n;i++) 
		c[x[i]=s[i]]++;
    for(i=1;i<m;i++) 
		c[i]+=c[i-1];
    for(i=n-1;i>=0;i--) 
		sa[--c[x[i]]]=i;
    for(j=1;j<=n;j<<=1) 
	{
        p=0;
        for(i=n-j;i<n;i++) 
			y[p++]=i;
        for(i=0;i<n;i++) 
            if(sa[i]>=j) 
                y[p++]=sa[i]-j;
        for(i=0;i<m;i++) 
			c[i]=0;
        for(i=0;i<n;i++) 
			c[x[y[i]]]++;
        for(i=1;i<m;i++) 
			c[i]+=c[i-1];
        for(i=n-1;i>=0;i--) 
			sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1,x[sa[0]]=0;
        for(i=1;i<n;i++) 
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
        if(p>=n) 
			break;
        m=p;
    }
}
 
void get_height(int s[],int n)//n为添加0后的总长
{
    int i,j,k=0;
    for(i=0;i<=n;i++)
        rk[sa[i]]=i;
    for(i=0;i<n;i++) 
	{
        if(k) 
			k--;
        j=sa[rk[i]-1];
        while(s[i+k]==s[j+k]) 
			k++;
        height[rk[i]]=k;
    }
}

void solve(int base=128)
{
	build_sa(s,len+1,base);
	get_height(s,len);
}

LL cal(bool state)
{
	LL sum=0,ans=0;
	int top=0;
	for(int i=2;i<=len;i++)
	{
		if(height[i]<k)
		{
			sum=top=0;
		}
		else
		{
			int num=0;
			if(state&&sa[i-1]<mark||!state&&sa[i-1]>mark)
			{
				num++;
				sum+=height[i]-k+1;
			}
			while(top&&Stack[top]>height[i])
			{
				sum-=1LL*cnt[top]*(Stack[top]-k+1);
				sum+=1LL*cnt[top]*(height[i]-k+1);
				num+=cnt[top];
				top--;
			}
			if(num)
			{
				top++;
				Stack[top]=height[i];
				cnt[top]=num;
			}
			if(state&&sa[i]>mark||!state&&sa[i]<mark)
				ans+=sum;
		}
	}
	return ans;
}

int main()
{
//	freopen("input.txt","r",stdin);
//	ios::sync_with_stdio(false);
	while(scanf("%d",&k)!=EOF&&k)
	{
		scanf("%s",str);
		mark=strlen(str);
		str[mark]=1;
		scanf("%s",str+mark+1);
		len=strlen(str);
		for(int i=0;i<=len;i++)
			s[i]=str[i];
		solve();
		printf("%lld\n",cal(true)+cal(false));
	}







	
	
	
	
	
	
	
	
	
	return 0;
}

 

发布了558 篇原创文章 · 获赞 16 · 访问量 1万+

Guess you like

Origin blog.csdn.net/qq_45458915/article/details/104031754