poj3415 Common Substrings (后缀数组+单调队列)
来源:互联网 发布:中国茶叶出口数据2017 编辑:程序博客网 时间:2024/03/29 17:37
Description
A substring of a string T is defined as:
Given two strings A, B and one integer K, we define S, a set of triples (i, j, k):
You are to give the value of |S| for specific A, B and K.
Input
The input file contains several blocks of data. For each block, the first line contains one integer K, followed by two lines containing strings A and B, respectively. The input file is ended by K=0.
1 ≤ |A|, |B| ≤ 105
1 ≤ K ≤ min{|A|, |B|}
Characters of A and B are all Latin letters.
Output
For each case, output an integer |S|.
Sample Input
2aababaaabaabaa1xxxx0
Sample Output
225
题意:给你2个字符串,让你分别在两个字符串中找到一个相同的子串,并且这两个相同串的长度要大于等于k,求这样的子串个数。
思路:这题思路不好想啊。我们知道,一个字符串的子串可以由母串的一个后缀的前缀表示,所以题目就变为求A中所有后缀的前缀和B中所有后缀的前缀公共前缀长度大于等于k的对数。我们可以把两个串连接起来,并且在两个串的中间插入一个以前没有出现过的字符(注意:这个字符的大小不能是0,即不能和最后一个我们自己添加的字符的大小相同,不然会错 = =),然后先求出sa[],height[]。按height[]值分组后,接下来的工作便是快速的统计每组中后缀之间的最长公共前缀之和。扫描一遍,每遇到一个B的后缀就统计与前面的A 的后缀能产生多少个长度不小于k 的公共子串,这里A 的后缀需要用一个单调的栈来高效的维护,然后对A也这样做一次。
#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<vector>#include<map>#include<set>#include<string>#include<bitset>#include<algorithm>using namespace std;#define lson th<<1#define rson th<<1|1typedef long long ll;typedef long double ldb;#define inf 99999999#define pi acos(-1.0)#define M 100050#define maxn 200050char s1[M],s2[M];int sa[maxn],a[maxn];int wa[maxn],wb[maxn],wv[maxn],we[maxn];int rk[maxn],height[maxn];int cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l];}void build_sa(int *r,int n,int m){ int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++)we[i]=0; for(i=0;i<n;i++)we[x[i]=r[i]]++; for(i=1;i<m;i++)we[i]+=we[i-1]; for(i=n-1;i>=0;i--)sa[--we[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p){ for(p=0,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<n;i++)wv[i]=x[y[i]]; for(i=0;i<m;i++)we[i]=0; for(i=0;i<n;i++)we[wv[i]]++; for(i=1;i<m;i++)we[i]+=we[i-1]; for(i=n-1;i>=0;i--)sa[--we[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; }}void calheight(int *r,int n){ int i,j,k=0; for(i=1;i<=n;i++)rk[sa[i]]=i; for(i=0;i<n;height[rk[i++] ]=k){ for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++); }}int q[111111][3]; //0表示高度,1表示宽度,2表示时间int main(){ int n,m,i,j,k; int front,rear,len1,len2; ll sum,kuan,tot; //sum表示最后的答案,kuan表示单调队列里面每一个元素的宽度 while(scanf("%d",&k)!=EOF && k!=0) { scanf("%s%s",s1,s2); n=0; len1=strlen(s1); len2=strlen(s2); for(i=0;i<len1;i++){ a[n++]=s1[i]-'a'+98; } a[n++]=1; for(i=0;i<len2;i++){ a[n++]=s2[i]-'a'+98; } a[n]=0; build_sa(a,n+1,130); calheight(a,n); sum=0; for(i=1;i<=n;i++){ if(height[i]<k){ front=1,rear=0; tot=0; //tot表示所有面积和 continue; } kuan=0; while(front<=rear && q[rear][0]>=height[i]){ kuan+=q[rear][1]; tot-=q[rear][1]*(q[rear][0]-height[i]); rear--; } if(sa[i-1]<len1){ kuan++; tot+=height[i]-k+1; } rear++; q[rear][0]=height[i];q[rear][1]=kuan; if(sa[i]>len1){ sum+=tot; } } for(i=1;i<=n;i++){ if(height[i]<k){ front=1,rear=0; tot=0; //tot表示所有面积和 continue; } kuan=0; while(front<=rear && q[rear][0]>=height[i]){ kuan+=q[rear][1]; tot-=q[rear][1]*(q[rear][0]-height[i]); rear--; } if(sa[i-1]>len1){ kuan++; tot+=height[i]-k+1; } rear++; q[rear][0]=height[i];q[rear][1]=kuan; if(sa[i]<len1){ sum+=tot; } } printf("%lld\n",sum); } return 0;}
- poj3415 Common Substrings (后缀数组+单调队列)
- poj3415 Common Substrings,后缀数组、单调栈
- [POJ3415]Common Substrings && 后缀数组+单调栈
- POJ3415:Common Substrings(后缀数组+单调栈)
- poj3415 Common Substrings (后缀数组+单调栈)
- POJ3415 Common Substrings 【后缀数组 + 单调栈】
- POJ3415--Common Substrings(后缀数组+单调栈优化)
- poj3415 Common Substrings(后缀数组,单调栈)
- [POJ3415]Common Substrings(后缀数组+单调栈)
- POJ3415 Common Substrings(后缀数组,单调栈)
- poj Common Substrings(后缀数组&单调队列)
- 【POJ3415】Common Substrings 后缀自动机
- Common Substrings 后缀数组+单调栈
- POJ 3415 Common Substrings(后缀数组+单调栈)
- POJ 3415 Common Substrings 后缀数组 计数 单调栈优化
- 【POJ】3415 Common Substrings 【后缀数组+单调栈】
- POJ 3415 Common Substrings 后缀数组 + 单调栈维护
- poj 3415 Common Substrings(后缀数组+单调栈)
- poj1698二分图多重匹配
- mybatis关闭缓存
- 对线程新的自我理解
- SAP删除会计科目 OBR2
- NSURLSession的基本使用
- poj3415 Common Substrings (后缀数组+单调队列)
- POJ 3744 Scout YYF I (矩阵相乘+概率DP)
- 十一、图的存储---(2)邻接矩阵和邻接表
- Leetcode - Compare Version Numbers
- HDU 1166 线段树
- NSURLSession的介绍和说明
- Android 发布项目到 jcenter 遇到的坑
- linux上修改时间
- iOS视图控制器编程指南 --- 视图控制器层次结构