浅谈与LCS有关的“求尾头衔接形成的最长字符串”问题

浅谈与LCS有关的“求尾头衔接形成的最长字符串”问题

小小的声明:

本人还属新手,如遇文章错误,还请多多包涵,同时也欢迎评论区提出,定感激不尽
题目来源

题目描述

丁姐姐最近迷上了LCS(The longest common substring)! 今天她想找个其它东西玩,于是她找到了两个字符串A和B,现在她想知道它们尾头衔接形成的最长字符串,例如A = abc,B = bca从A的尾部开始,A串的bc与B串的bc头尾衔接。

输入描述:

输入数据包含多个测试样例,每个测试样例占两行,第一行是字符串A,第二行是字符串B,保证每个字符串的长度不超过1010。

输出描述:

A和B尾头衔接形成的最长字符串,对于每个测试实例,输出一行,若两个字符串不衔接,输出"NULL!"(包含引号)。

示例1

输入

abc
bca
wad
ad
as
asd
wa
aw
wa
wwa

输出

bc
ad
as
a
“NULL!”

分析

此题题意很容易懂,关键在于需设定一个标志判断找没找到符合标准的子序列以及如何将两个数组进行比对
对于如何比对,这里有两种做法:第一,可利用循环一一比对;第二,可利用字符串函数提取相关子串进行比对。

先来贴个代码(别急,有详细解释呢!!!)

Code one:

#include<stdio.h>
#include<string.h>
int main()
{
    char a[1011],b[1011];
    int flag;
    while(scanf("%s%s",&a,&b)!=EOF)
          /*
          等价于while(~scanf("%s%s",a,b)),"~"为取反位运算符
          "EOF"为"end of file"的缩写,当输入为"Ctrl+Z"时结束输入
          */
   {
        int la=strlen(a);
        int lb=strlen(b);
        int len=la;
        if(lb<la) len=lb;//定义一个len记录最短字符串长度,因只需输出相同的序列,故用最短的字符串长度循环
        /*
        还阔以酱紫:
        len = min(la, lb)
        不过这样要加#include<algorithm>
        或者直接用C++万能头文件(不过有些刷题网站上不允许)
        */
        for(;len>=0;len--)//关键部分
            //由于之前len有值,所以此处len就不用初始化,节省代码长度
            /*
            先假设相同序列为两数组中最短的那个,假设为3,一一比对。
            */
        {
            flag=1;//flag作为标志变量,一般取0和1,具体取值根据题目要求
            for(int i=0;i<len;i++)//比对次数即为最小数组长度,假设输入的为3
            {
                if(a[la-len+i]!=b[i])
                /*
                假设:表示将a数组与b数组”尾首"对照三个字符,有一个不同直接
                退出i循环继续比对两个字符,若相同则直接退出len循环,并输出
                若直到最后,即len=0还没有找到相同的,则退出len后,输出"NULL!"
                */
                {
                    flag=0;
                    break;
                }
            }
            if(flag)//这时flag的意义就显现出来了,即防止退出i循环后直接退出len循环
            {
                break;
            }
        }
        printf(len == 0 ? "\"NULL!\"\n" : "%s\n", *a[la-len]);
        //注意:题干中有“(包含引号)”!!!
        //len=0表明循环执行到最后一步,a[],b[]中仍没有相同的字符
        /*等价于:
        if(len==0)
            printf("\"NULL!\"\n");
        else
            printf("%s\n", &a[la-len]);
        显然上面的三目运算符代码长度更短,在恰当的时机使用可以将复杂问题简单化。
        */
    }
    return 0;
}
再来看看一串代码

Code two:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
/*
typedef作用是为一种数据类型定义一个新名字(包括结构体等自定义和内部的数据类型)
一般为了方便输入可将long long重新定义为ll
*/
int main()
{
  string a,b,c;
  while(cin>>a>>b)
  {
    bool flag=false;//标记,作用同code2的flag
    for(ll i=0;i<a.size();i++)
    {
    	c=a.substr(i);

        if(b.find(c)==0)
        {
            flag=true;
            cout<<c<<endl;
            break;
        }
    }
    if(!flag) cout<<"\"NULL!\""<<endl;//没找到则 !flag=true
  }
}

小结

两串代码都定义了标志变量作为是否找到的标志,为解决问题做了很大一部分贡献;
Code one是利用for循环遍历相关子串,从而找出与题意相符的子串,编写程序时要非常清楚循环内容;而Code two则是利用函数的思想简化了相关循环,理解上更占优势,但对函数的积累量以及函数的恰当运用能力要求比较高。

参考网页

typedef
substr函数
find函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值