1. 程式人生 > >poj 1934 Trip 多個最長公共子序列

poj 1934 Trip 多個最長公共子序列

題目要你按字典序輸出兩個字串的多個最長公共子序列

思路:

先用動態規劃求兩個字串的最長公共子序列的儲存在dp[i][j];dp[i][j]表示s1字串1is2字串1j的最長公共子序列的長度

然後用兩個變數last1[i][j],last2[i][j]來分別儲存字元j(a的序號為0b的序號為1.....z的序號為25)在字串1-i中出現的最大標號,要是字元j沒有出現,last[i][j]= 0;

然後從兩個字串的長度len1len2開始列舉a---z字元,比如開始 t1 = last1[len1][0], t2 = last2[len2][0]表示as1字串1---len1的最大下標為

t1, s2字串1--len2的最大下標為t2,那麼若dp[t1][t2] 的值為s1s2的最大公共子序列長度cnt則表示這個字元符合,儲存起來,否則列舉下一個字元b。若滿足情況的話,在繼續在t1-1 t2 - 1 符合最大公共子序列為cnt - 1的字串儲存,如此迴圈,知道到達最長公共子序列為0時結束。把儲存的字串放入set集合裡面,讓它按字典序排序。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <set>
using namespace std;

int const maxn = 100;
char s1[maxn], s2[maxn], tmp[maxn];
int dp[maxn][maxn], last1[100][30], last2[100][30], len1, len2, cnt;
set<string> collection;

void LCA();
void handle(char s[], int len, int last[][30]);
void find(int index1, int index2, int len);

int main()
{
   
    scanf("%s %s", &s1[1], &s2[1]);
    LCA();
    
    handle(s1, len1, last1);
    handle(s2, len2, last2);
    
    cnt = dp[len1][len2];
    tmp[cnt+1] = '\0';
    find(len1, len2, cnt);
    for(set<string>::iterator iter = collection.begin(); iter != collection.end(); iter++)
        printf("%s\n", iter->c_str());
    
    return 0;
}

void LCA()
{
    int i, j;
    for(i = 1; s1[i] != '\0'; i++)
    {
        for(j = 1; s2[j] != '\0'; j++)
        {
            if(s1[i] == s2[j])
                dp[i][j] = dp[i-1][j-1] + 1;
            else if(dp[i-1][j] >= dp[i][j-1])
                dp[i][j] = dp[i-1][j];
            else
                dp[i][j] = dp[i][j-1];
        }
    }
    len1 = i - 1;
    len2 = j - 1;
}

void handle(char s[], int len, int last[][30])
{
    for(int i = 0; i < 26; i++)
    {
        char c = 'a' + i;
        for(int j = 1; j <= len; j++)
        {
            int k;
            for(k = j; k >= 1; k--)
            {
                if(c == s[k])
                {
                    last[j][i] = k;
                    break;
                }
            }
            
            if(k == 0)
                last[j][i] = 0;
        }
    }
}

void find(int index1, int index2, int len)
{
    if(len <= 0)
    {
        collection.insert(&tmp[1]);
        return;
    }
    
    if(index1 > 0 && index2 > 0)
    {
        for(int i = 0; i < 26; i++)
        {
            int t1 = last1[index1][i];
            int t2 = last2[index2][i];
            if(dp[t1][t2] == len)
            {
                tmp[len] = 'a' + i;
                find(t1 - 1, t2 - 1, len - 1);
            }
        }
    }
}


相關推薦

poj 1934 Trip 公共序列

題目要你按字典序輸出兩個字串的多個最長公共子序列 思路: 先用動態規劃求兩個字串的最長公共子序列的儲存在dp[i][j];dp[i][j]表示s1字串1到i和s2字串1到j的最長公共子序列的長度 然後用兩個變數last1[i][j],last2[i][j]來分別儲存字元j

POJ 1458 - Common Subsequence(公共序列) 題解

void 方式 mem strong 輸出 inline ron eof init 此文為博主原創題解,轉載時請通知博主,並把原文鏈接放在正文醒目位置。 題目鏈接:http://poj.org/problem?id=1458 題目大意: 有若幹組數據,每組給出兩個字符

poj——1159(dp之公共序列

注:C++執行時Runtime Error,G++過了。(這編譯器,真無語了)。 #include <iostream> #include <cmath> #include

spoj LCS2(串的公共序列,字尾自動機)

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

Human Gene Functions POJ 1080 公共序列變形

cee diff print bmi ces -s compare %d determine Description It is well known that a human gene can be considered as a sequence, consisting

POJ 1458 - Common Subsequence(公共串)

strlen cstring algorithm 鏈接 space %d ace -s set 此文為博主原創題解,轉載時請通知博主,並把原文鏈接放在正文醒目位置。 題目鏈接:http://poj.org/problem?id=1458 AC代碼:

[poj 2274]後綴數組+公共序列

max %d eight har 題目 while color sca 鏈接 題目鏈接:http://poj.org/problem?id=2774 後綴數組真的太強大了,原本dp是n^2的復雜度,在這裏只需要O(n+m)。 做法:將兩個串中間夾一個未出現過的字符接起來,然

BZOJ 2946 POI2000 公共串 後綴自動機(公共串)

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

資料結構演算法題/兩字串的公共序列

一,問題描述 給定兩個字串,求解這兩個字串的最長公共子序列(Longest Common Sequence)。比如字串1:BDCABA;字串2:ABCBDAB 則這兩個字串的最長公共子序列長度為4,最長公共子序列是:BCBA   二,演算法求解 這是一個動態規劃的題目。

POJ-1458 公共序列

這個題的意思就是說: 給一個序列 A 和 B ,讓你求他們的共同的子序列的長度,這些子序列可以不在原來的字串中連續排列。 這個題的話,我們可以使用動態規劃的思路,我們假設 MaxLen [ i ] [ j ] 是 A 串和 B 串中從一開始的,A 串中的的第 i 個字元和B 串中的第 j 個

求解兩字串的公共序列

一,問題描述 給定兩個字串,求解這兩個字串的最長公共子序列(Longest Common Sequence)。比如字串1:BDCABA;字串2:ABCBDAB 則這兩個字串的最長公共子序列長度為4,最長公共子序列是:BCBA 二,演算法求解 這是一個動態規劃的題目

POJ 1458 簡單dp 公共序列

要求:輸出最長公共子序列的長度 方法:dp裸題 1.狀態:dp[i][j]表示第一個序列的前i個字元和第二個序列的前j個字元的最長公共子序列的長度。 2.狀態轉移方程在程式碼中。 3.首要是程式碼規範化,然後才是找bug。 #include<stdio.h> #inc

poj~公共序列公共

最長公共子序列 poj1458 問題描述 給出兩個字串,求出這樣的一個最長的公共子序列的長度: 子序列中的每個字元都能在兩個原串中找到, 而且每個字元的先後順序和原串中的先後順序一致。 S

問題描述:求兩字串str1、str2的公共序列

首先明白兩個區別: 1、最長公共子串:子串是串的一個連續的部分,在原字串中位置是連續的 2、最長公共子序:不改變序列的順序,從序列中去掉任意的元素而獲得新的序列,也就是說子序在原字串中位置可以不連續。 遞推方程: 步驟:1序列str1和序列str2   ·長度分別為m和

1060 Nearest Sequence (三陣列的公共序列

Description         Do you remember the "Nearest Numbers"? Now here comes its brother:"Nearest Sequence".Given three sequences of char,tell me the lengt

poj公共序列公共

Description A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X =

poj 1159 Palindrome(公共序列 + 滾動陣列)

http://poj.org/problem?id=1159 題意:給定一個字串,問最少插入多少個字元,使得該字串變成迴文字串。 思路:原字串序列是X,逆序列是Y,則最少需要補充的字母數=X的長度-X

POJ 1458 Common Subsequence(公共序列LCS)

題意:        給你兩個字串, 要你求出兩個字串的最長公共子序列長度. 分析:        本題不用輸出子序列,很簡單,直接處理即可.        首先令dp[i][j]==x表示A串

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

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

POJ 1159 公共序列的應用

DP已經弱到不能再弱的程度了。。。。那就從最基本的做起吧!! 看隊友部落格裡面有這題,做了,讀完題,沒思路,才知道,一個叫最長公共子序列的東西不知道(注意與最長公共子串分開) 最長公共子序列作法: dp[i][j] 表示s1串中前i個字元,s2串中前j個字元所組成的兩個串的