POJ3729 Facer’s string 后缀数组

Facer’s string

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 1783   Accepted: 537

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 nm and k where n represents the length of S1m 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 ≤ nm ≤ 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

大致意思: a串所有后缀中,有多少个后缀与b串的所有后缀的lcp的最大值==k。。

a b串先连接一下,,中间加一个不会出现的数值,,我选了inf。。

然后求sa,lcp数组。。

可以先求大于等于k的后缀个数 ,再减去大于等于k+1的个数就是答案了。。

  1 #include <set>
  2 #include <map>
  3 #include <cmath>
  4 #include <ctime>
  5 #include <queue>
  6 #include <stack>
  7 #include <cstdio>
  8 #include <string>
  9 #include <vector>
 10 #include <cstdlib>
 11 #include <cstring>
 12 #include <iostream>
 13 #include <algorithm>
 14 using namespace std;
 15 typedef unsigned long long ull;
 16 typedef long long ll;
 17 const int inf = 0x3f3f3f3f;
 18 const double eps = 1e-8;
 19 const int maxn = 5e4+10;
 20 int s[maxn<<1];
 21 int len, k, sa[maxn << 1], tmp[maxn << 1], rank[maxn << 1];
 22 bool cmp(int i, int j)
 23 {
 24     if (rank[i] != rank[j])
 25         return rank[i] < rank[j];
 26     else
 27     {
 28         int x = (i + k <= len ? rank[i+k] : -1);
 29         int y = (j + k <= len ? rank[j+k] : -1);
 30         return x < y;
 31     }
 32 }
 33 void build_sa()
 34 {
 35     for (int i = 0; i <= len; i++)
 36     {
 37         sa[i] = i;
 38         rank[i] = (i < len ? s[i] : -1);
 39     }
 40     for (k = 1; k <= len; k *= 2)
 41     {
 42         sort(sa, sa+len+1,cmp);
 43         tmp[sa[0]] = 0;
 44         for (int i = 1; i <= len; i++)
 45         {
 46             tmp[sa[i]] = tmp[sa[i-1]] + (cmp(sa[i-1], sa[i]) ? 1 : 0);
 47         }
 48         for (int i = 0; i <= len; i++)
 49             rank[i] = tmp[i];
 50     }
 51 }
 52 int lcp[maxn << 1];
 53 void get_lcp()
 54 {
 55     for (int i = 0; i <= len; i++)
 56     {
 57         rank[sa[i]] = i;
 58     }
 59     int h = 0;
 60     lcp[0] = 0;
 61     for (int i = 0; i < len; i++)
 62     {
 63         int j = sa[rank[i]-1];
 64         if (h > 0)
 65             h--;
 66         for (; j+h < len && i+h < len; h++)
 67             if (s[j+h] != s[i+h])
 68                 break;
 69         lcp[rank[i]] = h;
 70     }
 71 }
 72 int solve(int kk, int n)
 73 {
 74     int res = 0;
 75     for (int i = 0; i <= len; i++)
 76     {
 77         if (lcp[i] >= kk)
 78         {
 79             int one = 0, two = 0;
 80             if (sa[i-1] < n)
 81                 one++;
 82             if (sa[i-1] > n)
 83                 two++;
 84             for (; i < len && lcp[i] >= kk; i++)
 85             {
 86                 if (sa[i] < n)
 87                     one++;
 88                 if (sa[i] > n)
 89                     two++;
 90             }
 91             if (two)
 92                 res += one;
 93         }
 94     }
 95     return res;
 96 }
 97 int main()
 98 {
 99     #ifndef ONLINE_JUDGE
100         freopen("in.txt","r",stdin);
101     #endif
102     int n,m,kk;
103     while (~ scanf ("%d%d%d",&n,&m,&kk))
104     {
105         for (int i = 0; i < n; i++)
106         {
107             scanf ("%d", s+i);
108             s[i]++;
109         }
110         s[n] = inf;
111         for (int i = n+1; i < n+1+m; i++)
112         {
113             scanf ("%d", s+i);
114             s[i]++;
115         }
116         len  = n + m + 1;
117         build_sa();
118         get_lcp();
119         printf("%d\n",solve(kk,n) - solve(kk+1,n));
120     }
121     return 0;
122 }
时间: 2024-10-07 12:46:17

POJ3729 Facer’s string 后缀数组的相关文章

POJ 3729 Facer’s string (后缀数组)

题目大意: 串1中有多少个后缀和 串2中的某个后缀 的lcp 为 k 思路分析: 先找出 长度至少为k的对数有多少. 再找出 至少为k+1的有多少 然后相减. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <map> #include <string> #define maxn 110005 using na

hdu 5030 Rabbit&#39;s String(后缀数组&amp;二分)

Rabbit's String Time Limit: 40000/20000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 288    Accepted Submission(s): 108 Problem Description Long long ago, there lived a lot of rabbits in the forest. One day, the

hdu 5030 Rabbit&#39;s String(后缀数组)

题目链接:hdu 5030 Rabbit's String 题目大意:给定k和一个字符串,要求将字符串拆分成k个子串.然后将每个子串中字典序最大的子串选出来,组成一个包含k个字符串的集合,要求这个集合中字典序最大的字符串字典序最小. 解题思路:网赛的时候试图搞了一下这道题,不过水平还是有限啊,后缀数组也是初学,只会切一些水题.赛后看了一下别人的题解,把这题补上了. 首先对整个字符串做后缀数组,除了处理出sa,rank,height数组,还要处理处f数组,f[i]表示说以0~sa[i]开头共有多少

POJ 2406 Power String 后缀数组

这题曾经用KMP做过,用KMP 做非常的简单,h函数自带的找循环节功能. 用后缀数组的话,首先枚举循环节长度k,然后比较LCP(suffix(k + 1), suffix(0)) 是否等于len - k, 如果相等显然k就是一个循环节. 得到LCP的话可以通过预处理出所有点和0的lcp就好了.另外倍增法构造后缀数组还有用RMQ来搞lcp nlogn是不行的,会超时,所以可以dc3走起了.. #include <cstdio> #include <cstring> #include

hdu 6194 string string string(后缀数组)

题目链接:hdu 6194 string string string 题意: 给你一个字符串,给你一个k,问你有多少个子串恰好在原串中出现k次. 题解: 后缀数组求出sa后,用height数组的信息去找答案. 每次用k长度的区间去卡height数组,求出该区间的lcp. 该区间的贡献就是ans=lcp-max(height[i],height[i+k]). 如果ans<=0,就不贡献. 比如 2 aaa 后缀数组为: 1 a 2 aa 3 aaa height为 0,1,2 现在扫到[1,2],

hdu 6194 沈阳网络赛--string string string(后缀数组)

题目链接 Problem Description Uncle Mao is a wonderful ACMER. One day he met an easy problem, but Uncle Mao was so lazy that he left the problem to you. I hope you can give him a solution.Given a string s, we define a substring that happens exactly k time

hdu-6194 string string string 后缀数组 出现恰好K次的串的数量

最少出现K次我们可以用Height数组的lcp来得出,而恰好出现K次,我们只要除去最少出现K+1次的lcp即可. #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; const int maxn = 100000 + 10; int t1[maxn], t2[maxn], c[maxn]; bool cmp(int

[Codechef CHSTR] Chef and String - 后缀数组

[Codechef CHSTR] Chef and String Description 每次询问 \(S\) 的子串中,选出 \(k\) 个相同子串的方案有多少种. Solution 本题要求不是很高,\(O(n^2)\) 统计每个出现次数子串个数即可. 我因为一个lld WA了一晚上(猛然意识到要%d读入long long的时候,之前一直没有翻车的原因是开了全局,如果是局部又不初始化就瞬间gg了,然鹅这个错误本地查不出来) #include <bits/stdc++.h> using na

Hackerrank--Ashton and String (后缀数组)

#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define maxn 100100 int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; int r[maxn],sa[maxn]; char str[maxn]; int cmp(int *r,int a,int b,int l) {return r[a]==r[b]&&a