给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符

思路:该题求连个子串的公共长度,不要求子串一定连续。子串长度有两种情况,第一种,其中任意一个子串的长度为0,那公共长度就一定为0   第二种,就是子串长度不为0,在子串长度不为0 的情况下又有2种情况,子串长度相等,子串长度不相等。   可用穷举法求解或动态规划法求解。 设第一字符串为A,第二个字符串为B,公共子串为C,i为A的下标j为B的下标

可以得到下列公式:

当其中有一个子串长度为0时                                                                                                                  i==0||j==0   c[i,j]=0;

当Ai==Bj时,跳过该字符,两个字符串当前位置同时后移,比较后面的字符                                c[i,j]=c[i-1,j-1]+1;

当Ai!=Bj时,分两个情况讨论:

第一种情况:i的位置固定不动,遍历j,找到i对应的字符串中与当前位置相同的元素

第二种情况:遍历i,找到j对应的字符串中与当前位置相同的元素,j的位置固定不动

然后对这两种情况进行比较,得到最大值,存入用来存储子串的数组中                                    c[i,j]=Math.Max((c[i,j-1]),(c[i-1,j]))

得到所有元素之后,就需要以字符串的形式输出,因为是子串,所以子串中的值无论在哪一个字符串中都存在,当i,j对应的位置一样时,然后把需要的值赋给要输出的字符串,

若对应的位置不一样就根据数组C通过字符串找到子串中的元素,然后赋值给要输出的字符串。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

using System;

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace 动态
{
    class Program
    {
        static void Main(string[] args)
        {
            StreamReader sr = new StreamReader(Console.OpenStandardInput());
            StreamWriter sw = new StreamWriter(Console.OpenStandardOutput());
            string s1 = sr.ReadLine();//定义一个字符串
            string s2 = sr.ReadLine();
            int len1 = s1.Length;//得到字符串的长度,方便后面的计算,因为很多地方都需要用到字符串长度
            int len2 = s2.Length;
            int[,] c = new int[len1 + 1, len2 + 1];//定义一个数组,用来存储最长子串的值
            string result = string.Empty;//定义结果字符串,先对它进行清空
            int i, j;
            //对两个字符串进行比较
            for (i = 1; i <= len1; i++)
            {
                for (j = 1; j <= len2; j++)
                {
                    if(s1[i-1]==s2[j-1])//若过比较的两个字符相等,就继续比较他们之后的字符
                    {
                        c[i, j] = c[i - 1, j - 1] + 1;
                    }
                    else//如果不相等,第一种情况是第二个字符串先往后移,找到与第一个字符串当前位置匹配的元素
                    {//第二种情况是第一个字符串先往后移,找到与第二个字符串当前位置匹配的元素,然后比较两种情况,得到最大值
                        c[i, j] = Math.Max((c[i - 1, j]), (c[i, j - 1]));
                        #region 比较的过程
                        //if (c[i, j - 1] >c[i - 1, j])
                        //{
                        //   c[i, j] = c[i, j - 1];
                        //}
                        //else
                        //{
                        //    c[i, j] = c[i - 1, j];
                        //}
                        #endregion
                    }
                }
            }
            //得到公共最长子串
            for (i = len1,j=len2;i>=1&&j>=1;)
            {
                if(s1[i-1]==s2[j-1])
                {
                    //如果两个字符串的值是一样的,把依据某一个字符串该字符添加到存储最长子串的字符串中就可以了,(如果是公共字符串,根据哪个字符串,把当前字符添加进去都是没有影响的)
                    result = s1[i - 1] + result;
                    i--;
                    j--;
                }
                else//如果字符串相应的位置不相等,就利用存储好子串的值的数组进行判断
                {
                    //根据某一字符串进行遍历
                    if(c[i,j-1] >c[i-1,j])
                    {
                        j--;
                    }
                    else
                    {
                        i--;
                    }
                }
            }
           Console.WriteLine(result);
        }
    }
}

你可能感兴趣的:(51Nod)