Codeforces Round #244 (Div. 2) D. Match & Catch 后缀数组

链接:

http://codeforces.com/contest/427/problem/D

题意:

给你两个字符串s1,s2,找出最短的子串出现在s1和s2中有且只有一次

题解:

还是把s1和s2连起来,求lcp。首先要知道得是,最短长度一定是sa数组中一定是相连的,

这样就只需要遍历一遍lcp数组,更新ans就可以了

ans = min(ans, max(lcp[i - 1], lcp[i + 1]) + 1)

代码:

31 int n, k;
32 int Rank[MAXN], tmp[MAXN];
33 int sa[MAXN], lcp[MAXN];
34
35 bool compare_sa(int i, int j) {
36     if (Rank[i] != Rank[j]) return Rank[i] < Rank[j];
37     else {
38         int ri = i + k <= n ? Rank[i + k] : -1;
39         int rj = j + k <= n ? Rank[j + k] : -1;
40         return ri < rj;
41     }
42 }
43
44 void construct_sa(string S, int *sa) {
45     n = S.length();
46     for (int i = 0; i <= n; i++) {
47         sa[i] = i;
48         Rank[i] = i < n ? S[i] : -1;
49     }
50     for (k = 1; k <= n; k *= 2) {
51         sort(sa, sa + n + 1, compare_sa);
52         tmp[sa[0]] = 0;
53         for (int i = 1; i <= n; i++)
54             tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);
55         for (int i = 0; i <= n; i++) Rank[i] = tmp[i];
56     }
57 }
58
59 void construct_lcp(string S, int *sa, int *lcp) {
60     int n = S.length();
61     for (int i = 0; i <= n; i++) Rank[sa[i]] = i;
62     int h = 0;
63     lcp[0] = 0;
64     for (int i = 0; i < n; i++) {
65         int j = sa[Rank[i] - 1];
66         if (h > 0) h--;
67         for (; j + h < n && i + h < n; h++)
68             if (S[j + h] != S[i + h]) break;
69         lcp[Rank[i] - 1] = h;
70     }
71 }
72
73 int main() {
74     ios::sync_with_stdio(false), cin.tie(0);
75     string s1, s2;
76     cin >> s1 >> s2;
77     int n1 = s1.length();
78     string s = s1 + "$" + s2;
79     construct_sa(s, sa);
80     construct_lcp(s, sa, lcp);
81     int ans = INF;
82     rep(i, 1, n + 1) if (lcp[i] > lcp[i - 1] && lcp[i] > lcp[i + 1])
83         if (!((sa[i] > n1) ^ (sa[i + 1] < n1)))
84             ans = min(ans, max(lcp[i - 1], lcp[i + 1]) + 1);
85     if (ans == INF) ans = -1;
86     cout << ans << endl;
87     return 0;
88 }
时间: 2024-10-10 02:57:36

Codeforces Round #244 (Div. 2) D. Match & Catch 后缀数组的相关文章

Codeforces Round #244 (Div. 2)——Match &amp; Catch

题目链接 题意:给两个长度分别为n和m的序列,现在有两种操作:1.分别选择两个序列的一个非空前缀,切两个前缀的最后一位相同,删除之,得到1分(只累计),消耗e:2.直接删除两个序列,消耗值定于两个序列之前删除的元素个数之和,并且使得得到的分有效(之前没有有效分) 分析: 首先,问题其实就是转化成,进行若干次操作1,然后进行操作2 还要找到一个判别标准,来评判较优的状态(贪心) 每次的消耗值比较大,其实可以计算出最大的删除次数,这个值不是很大 状态表示: 简单的,一个状态可以表示为串A的位置.串B

Codeforces Round #244 (Div. 2)

A. Police Recruits B. Prison Transfer A,B两个是水题. C. Checkposts DFS找出所有的环就行了. 每次搜索一个结点u时,给u加一个递增标号low[u],同时记录搜索u及u的子结点过程中遇到的最小标号minc,也就是当搜索u的子结点v时,minc = min(minc, low[v]).搜索完成后,如果minc < low[u],说明搜索u的子结点时又回到了u的父结点,也就是说u在一个环中,然后求出这个环的最小费用及取到最小费用的结点数. D.

Codeforces Round #244 (Div. 2)——Checkposts

题目链接 题意: 给定n个点,每个点有一个权值的有向图.现在需要选定一些点,使得这些点权值和最小,且满足:如果i能到达j且j能到达i,那么i.j可以只选一个 分析: 强联通模板题 //使用时只更新G完成构图 //scc_cnt从1开始计数 //pre[]表示点在DFS树中的先序时间戳 //lowlink[]表示当前点和后代能追溯到的最早祖先的pre值 //sccno[]表示点所在的双连通分量编号 //vector<int> G保存每个点相邻的下一个点序号 //stack<Edge>

Codeforces Round #244 (Div. 2) B. Prison Transfer

题目是选出c个连续的囚犯,而且囚犯的级别不能大于t #include <iostream> using namespace std; int main(){ int n,t,c; cin >> n >> t >> c; int a,cnt = 0, res =0;; for(int i = 0 ; i < n ; ++ i) { cin >> a; if(a > t ){ if(cnt > c-1) res+=cnt-c+1;

Codeforces Round #244 (Div. 2) A. Police Recruits

题目的意思就是找出未能及时处理的犯罪数, #include <iostream> using namespace std; int main(){ int n; cin >> n; int a,recruit = 0, crimes = 0;; for(int i = 0 ; i < n; ++ i){ cin >> a; if(a > 0) recruit+=a; else recruit?recruit-- : crimes++; } cout<&

Codeforces Round #244 (Div. 2)D (后缀自动机)

Codeforces Round #244 (Div. 2)D (后缀自动机) (标号为0的节点一定是null节点,无论如何都不能拿来用,切记切记,以后不能再错了) 这题用后缀自动机的话,对后缀自动机的很多性质有足够深刻的理解.没想过后缀数组怎么做,因为不高兴敲.... 题意:给出两个长度均不超过5000的字符串s1,s2,求这两个串中,都只出现一次的最短公共子串. 解题思路:求的是公共子串,然后对出现的次数又有限制,第一想法就是后缀自动机啊,后缀自动机处理子串出现次数再合适不过了.做法是这样的

Codeforces Round #244 (Div. 2)D (后缀自己主动机)

Codeforces Round #244 (Div. 2)D (后缀自己主动机) (标号为0的节点一定是null节点,不管怎样都不能拿来用,切记切记,以后不能再错了) 这题用后缀自己主动机的话,对后缀自己主动机的非常多性质有足够深刻的理解. 没想过后缀数组怎么做.由于不高兴敲... . 题意:给出两个长度均不超过5000的字符串s1,s2,求这两个串中,都仅仅出现一次的最短公共子串. 解题思路:求的是公共子串,然后对出现的次数又有限制,第一想法就是后缀自己主动机啊,后缀自己主动机处理子串出现次

Codeforces Round #244 (Div. 2) B. Prison Transfer 线段树rmq

B. Prison Transfer Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/problem/427/B Description The prison of your city has n prisoners. As the prison can't accommodate all of them, the city mayor has decided to transfer c

Codeforces Round #244 (Div. 2)B. Prison Transfer(想法题)

传送门 Description The prison of your city has n prisoners. As the prison can't accommodate all of them, the city mayor has decided to transfer c of the prisoners to a prison located in another city. For this reason, he made the n prisoners to stand in