`

求两个字符串的最长公共连续子序列(SAM实现)

阅读更多

//时间复杂度O(N)
#include <stdio.h>
#include <cstring>
const int R = 26;
const int N = 250005; //字符串的长度
struct node{
	node *next[R], *par; 
	int v; //该节点表示的子串的最大长度,最小长度即为par的最大长度+1,因此可以不用存下来
}nodes[N*2+100], *root;
int cnt;  //树中节点个数
node* newNode(int v, node* par){
	nodes[cnt].v = v; 
	nodes[cnt].par = par; 
	memset(nodes[cnt].next, 0, sizeof(node*)*R); 
	return &nodes[cnt++]; 
}
inline int id(char ch){
	return ch-'a'; 
}
//构造后缀自动机
void SAM(char* str, node*& root){
	cnt = 0; 
	node *last, *now, *np; 
	last = root = newNode(0, NULL);
	int i, k; 
	for(i = 0; str[i]; i++){
		now = last; 
		k = id(str[i]); 
		np = newNode(i+1, NULL); 
		while(now && ! now->next[k]){
			now->next[k] = np; 
			now = now->par; 
		}
		if(!now){
			np->par = root; 
		}else if(now->next[k]->v == now->v+1){
			np->par = now->next[k]; 
		}else{
			node* t = now->next[k]; 
			node* nt = newNode(now->v+1, t->par); 
			t->par = np->par = nt; 
			memcpy(nt->next, t->next, sizeof(node*)*R); 
			while(now && now->next[k] == t){
				now->next[k] = nt; 
				now = now->par;
			}
		}
		last = np; 
	}
}
inline void upMax(int& a, int tmp){
	if(a < tmp) a = tmp;
}
//求字符串sa和sb的最长公共连续子序列
int maxCommonLen(char* sa, char* sb){
	cnt = 0; 
	SAM(sa, root); 
	//test(); 
	node *now;
	now=root;
	int i, k, ans, len;
	ans = len = 0; 
	for(i = 0; sb[i]; i++){
		k = id(sb[i]); 
		if(now->next[k]){
			len++; 
			now = now->next[k];
		}else{
			while(now && ! now->next[k]){
				now = now->par; 
			}
			if(now){
				len = now->v + 1; 
				now = now->next[k]; 
			}else{
				now = root; 
				len = 0; 
			}
		}
		upMax(ans, len); 
	}
	return ans; 
}
 
分享到:
评论
1 楼 代码能力弱成渣 2012-12-08  
可以帮我看下我的代码么?我自己写的sam,也有ac过题的,但是最近跟别人讨论,说这个不是sam。
node *createnode(int l,node *fail)
{
    node *p=&memory[cnt];
    memory[cnt].len=l;
    memory[cnt].fail=fail;
    memset(memory[cnt++].next,NULL,sizeof(node *)*maxn);
    return p;
}

class SAM
{
    public:
    node *root;
    SAM()
    {
        root=NULL;
    }
    void Insert(char *str)
    {
        if(!root)
            root=createnode(0,NULL);
        node *loca=root;
        for(int i=0;str[i];i++)
        {
            int num=str[i]-'a';
            if(loca->next[num]==NULL)
                loca->next[num]=createnode(i+1,NULL);
            loca=loca->next[num];
        }
    }
    void Build()
    {
        std::queue<node *>s;
        while(!s.empty())
            s.pop();
        s.push(root);
        while(!s.empty())
        {
            node *loca=s.front();
            s.pop();
            for(int i=0;i<maxn;i++)
            {
                if(loca->next[i])
                {
                    if(loca==root)
                        loca->next[i]->fail=root;
                    else
                    {
                        node *tmp=loca->fail;
                        while(tmp)
                        {
                            if(tmp->next[i])
                                break;
                            tmp->next[i]=loca->next[i];
                            tmp=tmp->fail;
                        }
                        if(tmp==NULL)
                            loca->next[i]->fail=root;
                        else if(tmp->next[i]->len=tmp->len+1)
                        {
                            loca->next[i]->fail=tmp->next[i];
                        }
                        else
                        {
                            node *t=tmp->next[i];
                            node *nt=createnode(tmp->len+1,t->fail);
                            loca->next[i]->fail=t->fail=nt;
                            memcpy(nt->next,t->next,sizeof(node *)*maxn);
                            while(tmp&&tmp->next[i]==t)
                            {
                                tmp->next[i]=nt;
                                tmp=tmp->fail;
                            }
                        }
                    }
                    s.push(loca->next[i]);
                }
            }
        }
    }
};

相关推荐

    JavaScript自定义函数实现查找两个字符串最长公共子串的方法

    本文实例讲述了JavaScript自定义函数实现查找两个字符串最长公共子串的方法。分享给大家供大家参考,具体如下: //查找两个字符串的最长公共子串 function findSubStr(s1,s2){ var S=sstr= ,L1=s1.length,L2=s2....

    查询两个字符串的最长公共子序列

    利用指针来查询两个字符串的最长公共子序列,并输出的算法。

    Python求两个字符串最长公共子序列代码实例

    【Python求两个字符串最长公共子序列】 在编程领域,字符串操作是常见任务之一,而寻找两个字符串的最长公共子序列(LCS)是其中的一个经典问题。LCS是指两个字符串中都出现过的最长的连续子序列,但不考虑字符在...

    C语言求两个字符串的最长公共子串

    最长公共子串是指在两个或多个字符串中都存在的、且长度最长的连续字符序列。这个问题在文本处理、数据比较和生物信息学等领域都有广泛的应用。 首先,我们需要了解C语言中的字符串处理基础。在C语言中,字符串是以...

    最长公共子序列算法C#实现

    最长公共子序列(Longest Common Subsequence,简称LCS)是计算机科学中一种经典的问题,主要应用于比较和分析两个或多个序列的相似性。在这个问题中,目标是找到两个序列的最长子序列,这个子序列不需要在原序列中...

    动态规划法求字符串最长公共子序列

    动态规划法求字符串最长公共子序列

    求两字符串的最长公共子字符串.docx

    标题中的“求两字符串的最长公共子字符串”指的是在两个给定的字符串中找到它们共有的最长连续子串。这是一个经典的计算机科学问题,通常在字符串处理、文本比较和算法设计中出现。描述提到的“用穷举法完成”,指的...

    使用Java实现的计算两字符串相似度+最长公共子序列.zip

    在计算机科学领域,字符串处理是常见的一类任务,其中计算两个字符串的相似度以及找到它们的最长公共子序列(Longest Common Subsequence, LCS)是一个经典的问题。本篇将深入探讨这个问题,以及如何使用Java来解决...

    最长公共子序列算法设计与实现(c++).zip

    算法工程项目问题描述: 【题目】 动态规划思维训练——最长公共子序列算法的设计与实现 给定两个序列X={X1, X2,···,Xm}和...字符串Y:{ABCBDAB},则这两个字符串的最长公共子序列长度为4,最长公共子序列是:BCBA

    Java基于动态规划法实现求最长公共子序列及最长公共子字符串示例

    在求解最长公共子序列时,我们不是简单地将两个字符串拆分成独立的部分,而是寻找在不改变顺序的情况下存在于两个字符串中的最长的共享子序列。这个子序列不必是连续的,但必须保持原有的字符顺序。 最长公共子序列...

    最长公共子序列问题动态规划解决,二个或者三个字符串的

    哈工大算法实验二,最长公共子序列问题,动态规划解决LCS ...3.实现三个字符串最长公共子序列的动态规划算法 4.有界面源代码和实验报告!均为自己所做,正确运行。报告中还有用Excel表分析了算法的性能

    输入两个字符串,求它们最长公共字串的长度

    输入两个字符串, 求它们最长公共字串的长度

    最长公共子序列

    对于两个字符串X和Y,它们的公共子序列是同时存在于X和Y中的序列。最长公共子序列是指在所有公共子序列中长度最长的一个。例如,字符串"ABCDGH"和"AEDFHR"的最长公共子序列为"ADH"。 #### 三、动态规划求解 动态...

    求最长公共子序列动态规划

    通过填充这个二维数组,我们不仅可以得到两个字符串的最长公共子序列的长度,还可以通过回溯路径找出具体的子序列。具体来说,当 `dp[i][j] &gt; 0` 时,说明 `X[i-1]` 是 LCS 的一部分,我们可以根据 `dp[i][j]` 和 `...

    C语言求解最长公共子字符串问题及相关的算法分析

    请编写一个函数,输入两个字符串,求它们的最长公共子序列,并打印出最长公共子序列。 例如:输入两个字符串BDCABA和ABCBDAB,字符串BCBA和BDAB都是是它们的最长公共子序列,则输出它们的长度4,并打印任意一个子...

    最长公共子序列,最长100字符

    设序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列为Z={z1,z2,…,zk} ,则 (1)若xm=yn,则zk=xm=yn,且zk-1是xm-1和yn-1的最长公共子序列。 (2)若xm≠yn且zk≠xm,则Z是xm-1和Y的最长公共子序列。 (3)若xm≠...

    求最长公共子序列的LCS算法

    实现了求最长公共子序列的算法,内容简单易懂,代码也很短

Global site tag (gtag.js) - Google Analytics