1. 程式人生 > >Longest Common Substring II(字尾自動機求多個串的最長公共子串)

Longest Common Substring II(字尾自動機求多個串的最長公共子串)

A string is finite sequence of characters over a non-empty finite set Σ.

In this problem, Σ is the set of lowercase letters.

Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.

Now your task is a bit harder, for some given strings, find the length of the longest common substring of them.

Here common substring means a substring of two or more strings.

Input

The input contains at most 10 lines, each line consists of no more than 100000 lowercase letters, representing a string.

Output

The length of the longest common substring. If such string doesn't exist, print "0" instead.

Example

Input:
alsdfkjfjkdsal fdjskalajfkdsla aaaajfaaaa Output: 2
之前用kmp寫過類似的題,估計這個鐵定超,,
在一個串上建sam,然後開始掃,lcs表示當前串匹配到這個結點時和sam上串的最大公共子串長度,nlcs表示前n個的
ac程式碼
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define max(a,b) (a>b?a:b)
#define N 300010 
struct sam
{
	sam *pre,*son[26];
	int len,lcs,nlcs;
}que[N],*root,*tail,*b[N];
int tot;
void add(int c,int l)
{
	sam *p=tail,*np=&que[tot++];
	np->len=np->nlcs=l;
	tail=np;
	while(p&&p->son[c]==NULL)
	{
		p->son[c]=np;
		p=p->pre;
	}
	if(p==NULL)
		np->pre=root;
	else
	{
		sam *q=p->son[c];
		if(p->len+1==q->len)
			np->pre=q;
		else
		{
			sam *nq=&que[tot++];
			*nq=*q;
			nq->len=nq->nlcs=p->len+1;
			np->pre=q->pre=nq;
			while(p&&p->son[c]==q)
			{
				p->son[c]=nq;
				p=p->pre;
			} 
		}
	}
}
char str[N>>1];
int cnt[N>>1],len;
void build()
{
	int i,j;
	root=tail=&que[tot++];
	for(i=0;i<len;i++)
		add(str[i]-'a',i+1);
	memset(cnt,0,sizeof(cnt));
	for(i=0;i<tot;i++)
		cnt[que[i].len]++;
	for(i=1;i<=len;i++)
		cnt[i]+=cnt[i-1];
	for(i=0;i<tot;i++)
		b[--cnt[que[i].len]]=&que[i];
}
int main()
{
	int i;
	scanf("%s",str);
	len=strlen(str);
	build();
	while(scanf("%s",str)!=EOF)
	{
		sam *p=root;
		int l=0,i;
		for(i=0;str[i];i++)
		{
			int now=str[i]-'a';
			if(p->son[now])
			{
				l++;
				p=p->son[now];
			}
			else
			{
				while(p&&p->son[now]==NULL)
				{
					p=p->pre;
				}
				if(p==NULL)
				{
					l=0;
					p=root;
				}
				else
				{
					l=p->len+1;
					p=p->son[now];
				}
			}
			if(l>p->lcs)
				p->lcs=l;
		}
		for(i=tot-1;i>=0;i--)
		{
			p=b[i];
			if(p->lcs<p->nlcs)
				p->nlcs=p->lcs;
			if(p->pre&&p->pre->lcs<p->lcs)
				p->pre->lcs=p->lcs;
			p->lcs=0;
		}
	}
	int ans=0;
	for(i=0;i<tot;i++)
	{
		if(que[i].nlcs>ans)
			ans=que[i].nlcs;
	}
	printf("%d\n",ans);
} 


相關推薦

Longest Common Substring II字尾自動機公共

A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the set of lowercase letters. Substring, also called factor

2018.12.15【SPOJ-LCS2】Longest Common Substring II字尾自動機SAM

傳送門 解析: 這道題可以把所有串接在一起構建字尾自動機來做,但是那樣還不如寫字尾陣列。。。 所以這裡提供一個只有字尾自動機能實現的做法。 思路: 首先構建出第一個串的字尾自動機。 然後拿其他的串放到字尾自動機上面跑。同時更新答案。 程式碼裡面的

Longest Common Substring II 字尾自動機

A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the set of lowercase letters. Substring, also called factor

Longest Common Substring II字尾自動機

題目描述 傳送門 題意:給出若干串,求最長公共子串。 題解 這明明就是一道sa的題嘛,可是為了練習sam用sam來寫 首先對於第一個串構建sam 對於每一個狀態s,記錄一下它對於每一個串

字串公共動態規劃

code如下: //Longest common sequence, dynamic programming method void FindLCS(char *str1, char *str2) { if(str1 == NULL || str2 == NULL)

《程式設計師程式碼面試指南》字串公共

/** * 題目: * 給定兩個字串 str1 和 str2,返回兩個字串的最長公共子串。 *舉例: * str1 = "1AB2345CD",str2 = "12345EF",返回"2345"。 */ /** * 解答: * 經典動態規劃的方法可以做到時間複

BZOJ 2946 POI2000 公共 後綴自動機公共

調整 log spa size 暴力 pan emc auto 結束 題意概述:給出N個字符串,每個串的長度<=2000(霧。。。可能是當年的年代太久遠機子太差了),問這N個字符串的最長公共子串長度為多少。(N<=5) 拋開數據結構,先想想樸素做法。 設計一

如何兩字串的公共

此演算法的時間複雜度我還沒想清楚, 程式碼如下: #include<stdio.h>#include<string.h> char * maxsamesubstring(char *s1,char *s2){ int i,j,len,maxlen,i

SPOJ 1812 Longest Common Substring II 字尾自動機字串公共

題意: 給若干字串,求它們的最長公共子串的長度。 題解:字尾自動機。 對第一個串建立SAM,並拓撲排序。 用後面的串分別匹配。 對於SAM,每個節點新增兩個值ml,ans; ml代表該節點滿足單一字串時的最大值,匹配完一個字串後重置為0; an

【SPOJ】Longest Common Substring II 後綴自動機

公共子串 排序 -i max node bstr cst 後綴 post 【SPOJ】Longest Common Substring II (後綴自動機) 題面 Vjudge 題意:求若幹個串的最長公共子串 題解 對於某一個串構建\(SAM\) 每個串依次進行匹配 同時記

SPOJ 1811. Longest Common Substring LCS,兩字串的公共字尾自動機SAM

/* *********************************************** Author :kuangbin Created Time :2013-9-8 23:27:46 File Name :F:\2013ACM練習\專

SPOJ LCS2 - Longest Common Substring II 後綴自動機 的LCS

plus namespace sub align call 節點 inline cto res LCS2 - Longest Common Substring II no tags A string is finite sequence of cha

SPOJ 1812 LCS2 - Longest Common Substring II (後綴自動機)【兩種做法】

spoj name memset cstring pre fin cbi dcb 每次 手動博客搬家: 本文發表於20181217 23:54:35, 原地址https://blog.csdn.net/suncongbo/article/details/85058680 人

[SPOJ] (1812) Longest Common Substring II ---- SAM公共

題目傳送門 做法: 類似求兩個串的最長公共子串。 我們對第一個串建立自動機,然後把剩餘的n-1個串放進自動機上匹配。 每個串都儲存它們在每個狀態上的匹配的最大長度ml, 然後對於每個狀態,維護一個數組

LCS2 Longest Common Substring II (若干公共模板題

A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the set of lowercase letters. Substring,

常見演算法問題之公共問題Longest common substring problem

對於尋找兩個字串的最長公共子字串的問題,暴力搜尋的方式的時間複雜度將高達O(n^3), 而通過字尾樹的方式可將時間複雜度降低到O(n^2)。 以下是我實現的C++原始碼: #include <

公共Longest Common Substring

#include <iostream> using namespace std; int dp[30][30]; int maxlen; /* 記錄最大公共子串長度 */ int maxindex; /* 記錄最大公共子串在串1的起始位置 */ vo

LCS(longest common subsequence)公共序列演算法模板

看了幾分寫的相當好的部落格: 下面內容來轉載自上面文章 問題描述 什麼是最長公共子序列呢?好比一個數列 S,如果分別是兩個或多個已知數列的子序列,且是所有符合此條件序列中最長的,則S 稱為已知序列的最長公共子序列。     舉個例子,如:有兩條

公共問題 Longest Common Substring LCST 動態規劃

* 題目:  給定2個字串$str1, $str2, 返回2個字串的最長公共子串 e.g. $str1 = "1AB2345CD"; $str2 = "12345EF" 返回: "2345" 要求: 如果$str1 長度為M, $str2長度為N, 實現時間複雜度為

公共Longest Common SubStrings

Description 給出兩個字串,求出兩個字串的公共子串? sample Input encodingmy mydecoding sample Output coding