`

求两个字符串的最长公共连续子序列(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....

    求两个字符串的最长公共字串

    该问题主要涉及到两个或多个字符串之间共同拥有的最长连续字符序列的寻找。这种应用场景广泛存在于文本比对、生物信息学中的基因序列比对等多个领域。 #### 二、问题描述 题目要求编写一个C++程序来找到两个给定...

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

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

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

    本文实例讲述了C语言求两个字符串的最长公共子串的方法。分享给大家供大家参考。具体实现方法如下: #include "stdio.h" #include "string.h" #include "stdlib.h" void getCommon(char str1[],char str2[],char * ...

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

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

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

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

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

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

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

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

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

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

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

    最长公共子串是指在两个字符串中都连续出现且长度最长的子串,与最长公共子序列(Longest Common Subsequence,LCS)不同,它要求子串必须是原始字符串的连续片段。 为了解决最长公共子串问题,可以采用穷举法,这...

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

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

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

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

    PHP实现求两个字符串最长公共子串的方法示例

    在编程领域,最长公共子串(Longest Common Substring,LCS)问题是一个经典的问题,它寻找两个或多个字符串中的最长连续子序列,这个子序列同时存在于所有字符串中。在这个问题中,我们专注于PHP如何解决两个字符串...

    最长公共子序列的动态规划算法

    总结来说,最长公共子序列问题是一个典型的动态规划问题,通过使用C#编程语言,我们可以有效地求解两个字符串的最长公共子序列。这种算法在文本比较、生物信息学、软件工程等领域有广泛应用。理解并能实现这种算法...

    基于C++实现的通过动态规划查找最长公共子序列计算字符串之间相似度.zip

    在本项目中,我们关注的是使用C++编程语言来实现这一算法,通过动态规划的方法找到两个字符串的最长公共子序列。 动态规划是一种解决复杂问题的有效方法,它通过将大问题分解为相互关联的小问题,并存储这些小问题...

    最长公共子序列

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

Global site tag (gtag.js) - Google Analytics