代码改变世界

pojg2744找一个最长的字符串x,使得对于已经给出的字符串中的任意一个y,x或者是y的子串,或者x中的字符反序之后得到的新字符串是y的子串。

  youxin  阅读(2766)  评论(0编辑  收藏  举报

http://poj.grids.cn/practice/2744

描述
现在有一些由英文字符组成的大小写敏感的字符串,你的任务是找到一个最长的字符串x,使得对于已经给出的字符串中的任意一个y,x或者是y的子串,或者x中的字符反序之后得到的新字符串是y的子串。
输入
输入的第一行是一个整数t (1 <= t <= 10),t表示测试数据的数目。对于每一组测试数据,第一行是一个整数n (1 <= n <= 100),表示已经给出n个字符串。接下来n行,每行给出一个长度在1和100之间的字符串。
输出
对于每一组测试数据,输出一行,给出题目中要求的字符串x的长度。

 

这道题我刚开始认为很复杂,以为很难。但看了答案后才知道这题很简单。没有什么特殊的技巧。

问题分析:

假设x0是输入的字符串中最短的一个,x是所要找的字符串,x'是x反序后得到的字符串,显示,要么x是x0的子串,要么x' 是x0的子串,隐藏,只要取出x0的每个子串x,判断x是否满足给定的条件,找到其中最长的子串即可。

思路:先找出最短的字符串,然后利用最短字符串从长到短产生搜索子串,然后进行匹配检测,难点应该是从长到短产生搜索子串时不能有遗漏..

 刚开始提交时compile error,提示

error: ‘strrev’ was not declared in this scope
去看了下vs下面的警告。

warning C4996: 'strrev': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strrev. See online help for details.
1> d:\program files\visual studio\vc\include\string.h(250) : 参见“strrev”的声明

strrev有些编译器可能不支持,用标准的,前面加一个_即可。

要熟练的使用几个字符串处理函数:

char * strncpy(char *dest, char *src,size_tnum);

har *strstr(char *str1, char *str2);
功能:从字符串str1中查找是否有字符串str2,如果有,从str1中的str2位置起,返回str1中str2起始位置的指针,如果没有,返回null。
返回值:返回该位置的指针,如找不到,返回空指针。

char *strrev( char *str);

                  strrev(str) reverses all characters in str(except for the terminating null ). Returns a pointer to the reversed string.

最开始看到strrev有点奇怪,传递的是指针,而且函数确实改变了str,没必要在传一个同样的返回值。感觉没什么必要。但函数

原型就是如此。

复制代码
#include<stdio.h>
#include<string.h>

int t,n;
char str[100][101];

 

int searchMaxSubString(char *source)
{
    int subStrLen,sourceStrLen;
    subStrLen=sourceStrLen=strlen(source);
    int i,j;
    bool found;
    char subStr[101],revSubStr[101];
    while(subStrLen>0) //搜索不同长度的子串时,从最长的子串开始搜索
    {
        for(i=0;i<=sourceStrLen-subStrLen;i++)
        {
            strncpy(subStr,source+i,subStrLen);
            strncpy(revSubStr,source+i,subStrLen);
            subStr[subStrLen]=revSubStr[subStrLen]='\0'; //很重要的,否则结果错误

             _strrev(revSubStr);
             
            found=true;
            for(j=0;j<n;j++)
            {
                if(strstr(str[j],subStr)==NULL && strstr(str[j],revSubStr)==NULL)
                {
                    found=false;
                    break;
                }
            }
            if(found)
                return subStrLen;
        }
        subStrLen--;
    }
    return 0;
}

int main()
{
    int minStrLen;
    char minStr[101];
     
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        minStrLen=101;//每次必须重置
        for(int i=0;i<n;i++)
        {
            scanf("%s",str[i]);
            if(strlen(str[i])<minStrLen)
            {
                strcpy(minStr,str[i]);
                minStrLen=strlen(str[i]);
            }
        }
        int ret=searchMaxSubString(minStr);
        printf("%d\n",ret);
    }
}
复制代码

可以参考http://www.cnblogs.com/ns517/archive/2009/01/22/1380048.html,这个答案不好理解。

常见错误:

再用strncpy去子串时,需要在所取子串的默认添加字符串结束符 ' \0 '

 

 

编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
历史上的今天:
2012-08-06 JS Objects
2012-08-06 javascript 数字
2012-08-06 语法图
2012-08-06 转:JavaScript: 世界上最被误解的语言
点击右上角即可分享
微信分享提示