Description
從一個給定的串中刪去(不一定連續地刪去)0個或0個以上的字符,剩下地字符按原來順序組成的串。例如:“ ”,“a”,“xb”,“aaa”,“bbb”,“xabb”,“xaaabbb”都是串“xaaabbb”的子序列。(例子中的串不包含引號。)
編程求N個非空串的最長公共子序列的長度。限制:2<=N<=100;N個串中的字符只會是數字0,1,…,9或小寫英文字母a,b,…,z;每個串非空且最多含100個字符;N個串的長度的乘積不會超過30000。
Input
文件第1行是一個整數T,表示測試數據的個數(1<=T<=10)。接下來有T組測試數據。各組測試數據的第1行是一個整數Ni,表示第i組數據中串的個數。各組測試數據的第2到N+1行中,每行一個串,串中不會有空格,但行首和行末可能有空格,這些空格當然不算作串的一部分。
Output
輸出T行,每行一個數,第i行的數表示第i組測試數據中Ni個非空串的最長公共子序列的長度。
Sample
Input
1 3 ab bc cd
Output
0
解題思路:做過兩個字符串的Lcs,這個題就是多維的Lcs問題,如何將多維轉爲一維是這個題的難點,在網上看了看,都是設置一個index用來標識多個字符串的不同長度形態,即每組不同長度的字符串都有一個唯一標誌數字,這就將多維轉化爲一維,然後開始從後向前遍歷,詳細看代碼:
package cn.wy.sdut.dp;
import java.util.Arrays;
import java.util.Scanner;
//這組肯定爆
//1234567890abcdefghijkhlmnopqrstuvwxyz09876543321xyzuvwopqrstabcdefghiljklmnopqrstuvwxyz
//09876543321xyzuvwopqrstabcdefghiljklmnopqrstuvwxyz1234567890abcdefghijkhlmnop
//12354567897dkfjlsdjlsjflsjdl
public class Main {
static String[] s = new String[110]; //字符串數組
static int[] dp = new int[300100]; // 狀態數組, 很奇怪,c++不會爆數組,java不定個大點的就爆了
static int[] len = new int[110]; // 字符串長度
static int n;
public static int lcs(int[] tem) {
int index, i, j, ans;
// 如果有字符串長度爲0, 則返回0
for(i=0; i<n; i++) {
if(tem[i] == 0) return 0;
}
// 建立映射
for(index = tem[n-1] -1, i=n-1; i>=0; i--) {
index = index*len[i] + tem[i] -1;
System.out.println("index+"+i+":"+index);
}
//記憶化搜索
if(dp[index] >= 0) return dp[index];
//判斷是否所有串最後的字符都想等
for(i=1; i<n; i++) {
if(s[i].charAt(tem[i] - 1) != s[0].charAt(tem[0] - 1)) break;
}
//如果最後的字符相同, 最大長度 +1,之後恢復字符串長度,方便下次遍歷
if(i >= n) {
for(j=0; j<n; j++) {
tem[j]--;
}
ans = lcs(tem) + 1;
for(j=0; j<n; j++) {
tem[j]++;
}
} else { //否則,挨個枚舉,求最大值
ans = 0;
for(j=0; j<n; j++) {
tem[j]--;
int t = lcs(tem);
ans = Math.max(t, ans);
tem[j]++;
}
}
dp[index] = ans;
return ans;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int t = scan.nextInt();
for(int t1=0; t1<t; t1++) {
n = scan.nextInt();
int[] tem = new int[110]; //臨時數組,記錄臨時字符串長度
for(int i=0; i<n; i++) {
s[i] = new String();
s[i] = scan.next();
len[i] = tem[i] = s[i].length();
}
Arrays.fill(dp, -1);
System.out.println(lcs(tem));
}
scan.close();
}
}