POJ 3729 Facer's string (后缀数组)
来源:互联网 发布:pg报丧女妖网络限定 编辑:程序博客网 时间:2024/05/16 05:28
原题链接
Problem Description
Minifacer was very happy these days because he has learned the algorithm of KMP recently. Yet his elder brother, Hugefacer, thought that Minifacer needs a deeper understanding of this algorithm. Thus Hugefacer decided to play a game with his little brother to enhance his skills.
First, Hugefacer wrote down two strings S1 and S2. Then Minifacer tried to find a substring S3 of S1 which meets the following requirements: 1) S3 should have a length of k (which is a constant value); 2) S3 should also be the substring of S2. After several rounds, Hugefacer found that this game was too easy for his clever little brother, so he added another requirement: 3) the extended string of S3 should NOT be the substring of S2. Here the extended string of S3 is defined as S3 plus its succeed character in S1 (if S3 does not have a succeed character in S1, the extended string of S3 is S3 + ’ ’ which will never appear in S2). For example, let S1 be “ababc”, if we select the substring from the first character to the second character as S3 (so S3 equals “ab”), its extended string should be “aba”; if we select the substring from the third character to the fourth character as S3, its extended string should be “abc”; if we select the substring from the fourth character to the fifth character as S3, its extended string should be “bc”.
Since the difficult level of the game has been greatly increased after the third requirement was added, Minifacer was not able to win the game and he thought that maybe none of the substring would meet all the requirements. In order to prove that Minifacer was wrong, Hugefacer would like to write a program to compute number of substrings that meet the three demands (Note that two strings with same appearance but different positions in original string S1 should be count twice). Since Hugefacer do not like characters, he will use non-negative integers (range from 0 to 10000) instead.
Input
There are multiple test cases. Each case contains three lines: the first line contains three integers n, m and k where n represents the length of S1, m represents the length of S2 and k represents the length of substring; the second line contains string S1 and the third line contains string S2. Here 0 ≤ n, m ≤ 50000. Input ends with EOF.
Output
For each test case, output a number in a line stand for the total number of substrings that meet the three requirements.
Sample Input
5 5 2
1 2 1 2 3
1 2 3 4 5
5 5 3
1 2 1 2 3
1 2 3 4 5
Sample Output
2
1
题目大意
第一行输入n,m,k,代表第一个数列中有n个数,第二个数列中有m个数,k表示子序列的长度。现在要在第一个数列中找长度为k的子序列使得它同样是第二个数列的子序列,但是要保证这个子序列在第一个数列中的后一个数不能等于它在第二个数列中的后一个数。
解题思路
总体的思路就是求后缀数组然后对后缀进行分组。具体地来说,先将两个数列连接,中间用一个足够大的数隔开,然后求一次后缀数组,由于题目的特殊条件“ the extended string of S3 should NOT be the substring of S2.”,我们可以去用公共字串长度大于等于k的数量减去公共子串长度大于等于k+1的数量得到长度恰好等于k的数量。
AC代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<algorithm>#include<cmath>#include<vector>#include<string>#include<queue>#include<list>#include<stack>#include<set>#include<map>#define ll long long#define ull unsigned long long#define rep(i,n) for(int i = 0;i < n; i++)#define fil(a,b) memset((a),(b),sizeof(a))#define cl(a) fil(a,0)#define pb push_back#define mp make_pair#define ee 2.7182818#define PI 3.141592653589793#define inf 0x3f3f3f3f#define fi first#define se second#define eps 1e-7#define mod 1000000007llusing namespace std;const int size = 123456,INF = 1<<30;int rk[size],sa[size],height[size],w[size],wa[size],res[size];void getSa (int len,int up) { int *k = rk,*id = height,*r = res, *cnt = wa; rep(i,up) cnt[i] = 0; rep(i,len) cnt[k[i] = w[i]]++; rep(i,up) cnt[i+1] += cnt[i]; for(int i = len - 1; i >= 0; i--) { sa[--cnt[k[i]]] = i; } int d = 1,p = 0; while(p < len){ for(int i = len - d; i < len; i++) id[p++] = i; rep(i,len) if(sa[i] >= d) id[p++] = sa[i] - d; rep(i,len) r[i] = k[id[i]]; rep(i,up) cnt[i] = 0; rep(i,len) cnt[r[i]]++; rep(i,up) cnt[i+1] += cnt[i]; for(int i = len - 1; i >= 0; i--) { sa[--cnt[r[i]]] = id[i]; } swap(k,r); p = 0; k[sa[0]] = p++; rep(i,len-1) { if(sa[i]+d < len && sa[i+1]+d <len &&r[sa[i]] == r[sa[i+1]]&& r[sa[i]+d] == r[sa[i+1]+d]) k[sa[i+1]] = p - 1; else k[sa[i+1]] = p++; } if(p >= len) return ; d *= 2,up = p, p = 0; }}void getHeight(int len) { rep(i,len) rk[sa[i]] = i; height[0] = 0; for(int i = 0,p = 0; i < len - 1; i++) { int j = sa[rk[i]-1]; while(i+p < len&& j+p < len&& w[i+p] == w[j+p]) { p++; } height[rk[i]] = p; p = max(0,p - 1); }}int getSuffix(int s[],int len) { int up = 0; for(int i = 0; i < len; i++) { w[i] = s[i]; up = max(up,w[i]); } w[len++] = 0; getSa(len,up+1); getHeight(len); return len;}int a[123456];int n,m,k;int cal(int k,int len){ int le=0; int mo=0; int cnt=0; if(sa[1]<n) le++; else mo++; for(int i=2;i<=len;++i) { if(height[i]<k) { if(mo>0) cnt+=le; mo=0; le=0; } if(sa[i]<n) le++; else mo++; } return cnt;}int main(void){ while(scanf("%d%d%d",&n,&m,&k)!=EOF) { for(int i=0;i<n;++i) { scanf("%d",&a[i]); a[i]++; } a[n]=20000; for(int i=0;i<m;++i) { scanf("%d",&a[n+i+1]); a[n+i+1]++; } a[n+m+1]=0; int useless=getSuffix(a,n+m+2); cout<<cal(k,useless-1)-cal(k+1,useless-1)<<endl; } return 0;}
- POJ 3729 Facer’s string (后缀数组)
- POJ 3729 Facer’s string(后缀数组)
- POJ 3729 Facer's string (后缀数组)
- POJ 3729 Facer’s string (后缀数组 两串后缀的LCP为K的对数)
- POJ 3729 Facer’s string
- POJ 3729 Facer’s string
- POJ 3729 Facer’s string 笔记
- POJ题目3229 Facer’s string(后缀数组求a串长度为k子串有几个出现在b串)
- POJ-3717-Facer's Chocolate Dream
- Hdu 5030 Rabbit's String (后缀数组)
- 【后缀数组】 HDOJ 5030 Rabbit's String
- HDU 5030 Rabbit's String 后缀数组
- hdu 5030 Rabbit's String(后缀数组)
- hdu5030 Rabbit's String 后缀数组
- POJ 1734(后缀数组)
- POJ 3693(后缀数组)
- POJ 2774(后缀数组)
- POJ 3415(后缀数组)
- webstorm快捷键-自整理版
- 百度投资医疗行业,编制很多的虚假的疾病,关押了很多的正常人,让我错看了百度 怀念
- Proteus仿真AT89C52——双机通讯
- Oracel——创建表空间
- 总结篇:大型网站技术架构-性能(一)
- POJ 3729 Facer's string (后缀数组)
- 第三天总结
- hdu1394 Minimum Inversion Number
- ajax和jsonp的原生封装
- Markdown语法讲解及MWeb使用教程
- Comparable & Comparator用法
- 516. Longest Palindromic Subsequence
- LeetCode 279. Perfect Squares
- 为什么要有Mycat---Mycat的前世今生