SPOJ 220. Relevant Phrases of Annihilation(字尾陣列多次不重疊子串)
題目大意:給定N個串,求每個串至少出現兩次的最長子串。
解題思路:每個字串至少出現兩次且不可重疊的最長子串:二分列舉長度後在同一分組中對每一個字串保留一個最小的位置和一個最大的位置,最後檢視是否每個串在同一組中都有至少兩個字尾,並且字尾的座標差大於列舉的長度。
POJ Problem Set (classical)
220. Relevant Phrases of Annihilation
Problem code: PHRASES
You are the King of Byteland. Your agents have just intercepted a batch of encrypted enemy messages concerning the date of the planned attack on your island. You immedietaly send for the Bytelandian Cryptographer, but he is currently busy eating popcorn and claims that he may only decrypt the most important part of the text (since the rest would be a waste of his time). You decide to select the fragment of the text which the enemy has strongly emphasised, evidently regarding it as the most important. So, you are looking for a fragment of text which appears in all the messages disjointly at least twice. Since you are not overfond of the cryptographer, try to make this fragment as long as possible.
Input
The first line of input contains a single positive integer t<=10, the number of test cases. t test cases follow.Each test case begins with integer n (n<=10), the number of messages. The next n lines contain the messages, consisting only of between 2 and 10000 characters 'a'-'z', possibly with some additional trailing white space which should be ignored.
Output
For each test case output the length of longest string which appears disjointly at least twice in all of the messages.
Example
Input: 1 4 abbabba dabddkababa bacaba baba Output: 2
(in the example above, the longest substring which fulfills the requirements is 'ba')
Date: | 2004-10-11 |
Time limit: | 9s |
Source limit: | 50000B |
Memory limit: | 1536MB |
Languages: | All except: NODEJS PERL 6 SCM chicken VB.net |
Resource: | DASM Programming League 2004 (problemset 1) |
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <ctime>
#include <map>
#include <set>
#define eps 1e-9
///#define M 1000100
///#define LL __int64
#define LL long long
///#define INF 0x7ffffff
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
#define zero(x) ((fabs(x)<eps)?0:x)
#define mod 1000000007
#define Read() freopen("autocomplete.in","r",stdin)
#define Write() freopen("autocomplete.out","w",stdout)
#define Cin() ios::sync_with_stdio(false)
using namespace std;
inline int read()
{
char ch;
bool flag = false;
int a = 0;
while(!((((ch = getchar()) >= '0') && (ch <= '9')) || (ch == '-')));
if(ch != '-')
{
a *= 10;
a += ch - '0';
}
else
{
flag = true;
}
while(((ch = getchar()) >= '0') && (ch <= '9'))
{
a *= 10;
a += ch - '0';
}
if(flag)
{
a = -a;
}
return a;
}
void write(int a)
{
if(a < 0)
{
putchar('-');
a = -a;
}
if(a >= 10)
{
write(a / 10);
}
putchar(a % 10 + '0');
}
const int maxn = 200010;
int wa[maxn], wb[maxn], wv[maxn], ws1[maxn];
int sa[maxn];
int cmp(int *r, int a, int b, int l)
{
return r[a] == r[b] && r[a+l] == r[b+l];
}
void da(int *r, int *sa, int n, int m)
{
int i, j, p, *x = wa, *y = wb;
for(i = 0; i < m; i++) ws1[i] = 0;
for(i = 0; i < n; i++) ws1[x[i] = r[i]]++;
for(i = 1; i < m; i++) ws1[i] += ws1[i-1];
for(i = n-1; i >= 0; i--) sa[--ws1[x[i]]] = i;
for(j = 1, p = 1; p < n; j <<= 1, 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++) ws1[i] = 0;
for(i = 0; i < n; i++) ws1[wv[i]]++;
for(i = 1; i < m; i++) ws1[i] += ws1[i-1];
for(i = n-1; i >= 0; i--) sa[--ws1[wv[i]]] = y[i];
for(swap(x, y), 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++;
}
return ;
}
int rank[maxn], height[maxn];
void calheight(int *r, int *sa, int n)
{
int i, j, k = 0;
for(i = 1; i <= n; i++) rank[sa[i]] = i;
for(i = 0; i < n; height[rank[i++]] = k)
for(k?k--:0, j = sa[rank[i]-1]; r[i+k] == r[j+k]; k++);
return;
}
char str1[maxn], str2[maxn];
int seq[maxn];
int hash[maxn];
char str[110][1010];
int vis[110];
int Find(int x)
{
int s = hash[x];
for(int i = 0; i < s; i++)
{
int len = strlen(str[i]);
x -= len;
}
x -= s;
return x;
}
int pos[20][2];
bool judge(int mid, int n, int m)
{
for(int i = 2; i <= n; i++)
{
memset(vis, 0, sizeof(vis));
vis[hash[sa[i-1]]]++;
pos[hash[sa[i-1]]][0] = pos[hash[sa[i-1]]][1] = sa[i-1];
while(mid <= height[i])
{
int xp = hash[sa[i]];
if(!vis[xp])
{
vis[xp]++;
pos[xp][1] = pos[xp][0] = sa[i];
i++;
continue;
}
vis[xp]++;
pos[xp][0] = max(pos[xp][0], sa[i]);
pos[xp][1] = min(pos[xp][1], sa[i]);
i++;
}
int k;
for(k = 0; k < m; k++)
{
if(vis[k] < 2 || pos[k][0]-pos[k][1] < mid)
break;
}
if(k == m) return true;
}
return false;
}
void Del(int n, int len, int m)
{
int l = 1;
int r = len/2;
int xans = 0;
while(l <= r)
{
int mid = (l+r)>>1;
if(judge(mid, n, m))
{
l = mid+1;
xans = mid;
}
else r = mid-1;
}
cout<<xans<<endl;
}
int main()
{
int T;
cin >>T;
int n;
while(T--)
{
scanf("%d", &n);
memset(hash, -1, sizeof(hash));
int ans = 0;
int Min = maxn;
for(int i = 0; i < n; i++)
{
scanf("%s",str[i]);
int len = strlen(str[i]);
Min = min(Min, len);
for(int j = 0; j < len; j++)
{
seq[ans] = str[i][j];
hash[ans++] = i;
}
seq[ans++] = 200+i;
}
seq[ans] = 0;
da(seq, sa, ans+1, 310);
calheight(seq, sa, ans);
Del(ans, Min, n);
}
return 0;
}
相關推薦
SPOJ 220. Relevant Phrases of Annihilation(字尾陣列多次不重疊子串)
題目大意:給定N個串,求每個串至少出現兩次的最長子串。 解題思路:每個字串至少出現兩次且不可重疊的最長子串:二分列舉長度後在同一分組中對每一個字串保留一個最小的位置和一個最大的位置,最後檢視是否每個串在同一組中都有至少兩個字尾,並且字尾的座標差大於列舉的長度。 POJ P
SPOJ 220 Relevant Phrases of Annihilation(每個字串至少出現兩次且不重疊的最長子串)
題目:給定n個字串,求出每個字串至少出現兩次且不重疊的最長子串 將n個字串連線起來,中間用不同的特殊字元隔開。求出字尾陣列 二分答案,通過height值將字尾分組,判斷在每一組中,每個字串是否至少出現兩次 而且由於題目需要不重疊的子串,所以還要記錄每個字串位置的最大值
【字尾陣列】【spoj 220】Relevant Phrases of Annihilation
基本應用——每個字串至少出現兩次且不重複的最長子串 memset的mmin[]和mmax開大了簡直是作死,狂T不止。。。 //#define _TEST _TEST #include <cstdio> #include <cstring>
2018.11.30 spoj220 Relevant Phrases of Annihilation(字尾陣列+二分答案)
傳送門 程式碼: 先用特殊字元把所有字串連線在一起。 然後二分答案將 s a sa
2018.12.01【SPOJ220】Relevant Phrases of Annihilation(字尾陣列)(二分答案)
傳送門 解析: 套路題。 首先串成一串求一下SA。 然後按照二分出的 l e n
【SPOJ220】Relevant Phrases of Annihilation(後綴數組,二分)
spa std spoj lse map sign math vector mod 題意: n<=10,len<=1e4 思路: 1 #include<cstdio> 2 #include<cstring> 3 #incl
718. Maximum Length of Repeated Subarray 字尾陣列解最長公共子串 O(n log^2 n)時間複雜度
題意 找最長公共子串 思路 用dp的方法很容易在O(n^2)解決問題,這裡主要討論用字尾陣列的思路解決這個問題 字尾數組裡有兩個經典的概念或者稱為資料結構,就是字尾陣列SA,以及高度陣列LCP SA陣列的定義是:將原串S所有的字尾按字典序排序
字尾陣列求最長重複子串
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
SPOJ SUBST1 POJ 2406 POJ REPEATS 字尾陣列小結
//聰神說:做完了題目記得總結,方便以後複習。 SPOJ SUBST1 題意:給一個字串,求不同子串個數。 思路:假設所有子串都不同,答案為len*(len+1)/2;然而不是這樣... 下面我們就找出重複的子串: 首先先將字尾排序,對於字尾i能生成len-sa[i]個
字尾陣列+二分+--luoguP3649 [APIO2014]迴文串
傳送門 首先回文子串可以用 m a n a
POJ-1743 Musical Theme(最長不可重疊子串,字尾陣列+二分)
A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the piano. I
HDU 4622 Reincarnation (區間不相同子串個數:字串雜湊 | 字尾陣列 | 字尾自動機)
Problem Description Now you are back,and have a task to do: Given you a string s consist of
3693 Maximum repetition substring(字尾陣列求重複次數最多的連續重複子串)
Description The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same
POJ 3693 重複次數最多的連續重複子串 字尾陣列
題目大意就是求重複次數最多的連續重複子串。例如abababc 答案就是ababab 因為ab連續出現的次數最多 並且題目還要求輸出字典序最小的 比如abababcdcdcd ababab和cdcdcd都符合要求 但是ababab字典序小 具體做法參見羅穗騫的論文 窮舉
POJ 3693 Maximum repetition substring 字尾陣列求重複次數最多子串
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10488 Accepted: 3242 Description The repe
尋找一個字串中的最長重複子串(字尾陣列)&找出一個字串中最長不重複子串
一、尋找一個字串中的最長重複子串(字尾陣列) 字尾陣列其實可以看尋找一個字串中的最長重複子串(字尾陣列)作一個由字串s倒數i個字元組成的子串的集合,其中0<i<s.length(),例如 字串strstr的字尾陣列為: {r,tr,str,rstr,trstr,
3693 求這串字元中的重複次數最多的連續重複子串,多組答案輸出字典序最小的那個串(字尾陣列)
題目:求這串字元中的重複次數最多的連續重複子串,多組答案輸出字典序最小的那個串。 思路:與前一個題目幾乎一樣的,加上了字典序。多判斷就好 //#include<bits/stdc++.h> #include<iostream> #include
SPOJ 694 || 705 Distinct Substrings ( 後綴數組 && 不同子串的個數 )
sub 重復出現 clu lose print bool 種類 cas 子串 題意 : 對於給出的串,輸出其不同長度的子串的種類數 分析 : 有一個事實就是每一個子串必定是某一個後綴的前綴,換句話說就是每一個後綴的的每一個前綴都代表著一個子串,那麽如何在這麽多子串or後
bzoj 4032 [HEOI2015]最短不公共子串——字尾自動機
題目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032 不是 b 的子串的話就對 b 建字尾自動機,在 a 上列舉從每個位置開始的子串或者找子序列(子序列就是記錄 a 的前 i 個,走到 b 的 j 狀態用的最短長度),對應到自動機上看看能不能走下去
] 找工作知識儲備(2)---陣列字串那些經典演算法:最大子序列和,最長遞增子序列,最長公共子串,最長公共子序列,字串編輯距離,最長不重複子串,最長迴文子串
作者:寒小陽 時間:2013年9月。 0、前言 這一部分的內容原本是打算在之後的字串或者陣列專題裡面寫的,但看著目前火熱進行的各家網際網路公司筆試面試中,出現了其中的一兩個內容,就隨即將這些經典問題整理整理,單寫一