题意:
  给N个字符串,要求出一个序列,在该序列中,后一个串,是由前一个串加一个字母后得来的(顺序可以改动)。
  问最多能组成多长的序列。
思路:将给的字符串排序,再对所有的字符串按长度从小到大排序,若长度相同,则按字典序排。
     然后找出符合条件的字符串A和B(即B可由A加一个字母得来),建立边的关系。
        之后对所有根节点进行dfs深搜,如果当前的长度大于目前的maxlen,则更新,同时记录前驱节点。
   最后根据前驱节点,输出路径即可。

#include <stdio.h>
#include <map>
#include <string.h>
#include <algorithm>
#include <string>
#include <queue>
#include <vector>
#include <iostream> using namespace std;
const int maxn=;
int n=;
vector<int>son[maxn];
int fa[maxn]; //如果该节点有父节点,则fa[i]=1;否则为0,表示根节点
int tmp[maxn]; //dfs时的前驱
int pre[maxn]; //最大长度序列的前驱,也可以设置后驱,这样会方便点。
int ans[]; //输出的结果
int maxlen=; //序列的最大长度
int rear; //最长序列的尾节点 struct Word{
char str1[],str2[]; //str1为字符串,str2为对字符串中的字符排好序后的字符串
int len;
bool operator<(const Word tmp)const{
if(len==tmp.len){
if(strcmp(str2,tmp.str2)<=)
return true;
else
return false;
}
else
return len<tmp.len;
}
}word[maxn];
//判断字符串i和字符串j是否满足条件
bool isOk(int i,int j){
int l1=word[i].len;
int l2=word[j].len;
int idx=;
while(idx<l1&&word[i].str2[idx]==word[j].str2[idx])
idx++;
while(++idx<l2)
if(word[i].str2[idx-]!=word[j].str2[idx])
return false;
return true;
}
//深搜,确定以u为根节点到叶子节点的长度
void dfs(int u,int l){
if(son[u].empty()){
if(l>maxlen){
maxlen=l;
int k=u;
rear=u;
while(tmp[k]!=-){
pre[k]=tmp[k];
k=tmp[k];
}
pre[k]=-;
return;
}
}
int v;
for(int i=;i<son[u].size();i++){
v=son[u][i];
tmp[v]=u;
dfs(v,l+);
}
}
int main()
{
char s[];
while(scanf("%s",s)!=EOF){
strcpy(word[++n].str1,s);
strcpy(word[n].str2,s);
word[n].len=strlen(s);
sort(word[n].str2,word[n].str2+word[n].len);
}
sort(word+,word+n+);
memset(fa,,sizeof(fa));
for(int i=;i<=n;i++){
for(int j=i+;j<=n;j++){
if(word[i].len+==word[j].len){
if(isOk(i,j)){
son[i].push_back(j);
fa[j]=;
} }
//剪枝一下,从1766ms降到1266ms
else if(word[i].len+<word[j].len)
break;
}
}
memset(pre,-,sizeof(pre));
for(int i=;i<=n;i++){
//加上一个剪枝条件,不过速度没怎么变化。。。
if(!fa[i] && n-i+>maxlen){
memset(tmp,-,sizeof(tmp));
dfs(i,);
}
}
int p=rear;
int idx=;
ans[idx++]=p;
p=pre[p];
while(p!=-){
ans[idx++]=p;
p=pre[p];
}
for(int i=idx-;i>=;i--){
printf("%s\n",word[ans[i]].str1);
}
return ;
}

POJ 2004 Mix and Build (预处理+dfs)的更多相关文章

  1. Mix and Build(简单DP)

    Mix and Build Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3936 Accepted: 1203 Case Ti ...

  2. poj 1724 ROADS 很水的dfs

    题意:给你N个城市和M条路和K块钱,每条路有话费,问你从1走到N的在K块钱内所能走的最短距离是多少 链接:http://poj.org/problem?id=1724 直接dfs搜一遍就是 代码: # ...

  3. POJ 2831 Can We Build This One:次小生成树【N^2预处理】

    题目链接:http://poj.org/problem?id=2831 题意: 给你一个图,每条边有边权. 然后有q组询问(i,x),问你如果将第i条边的边权改为x,这条边是否有可能在新的最小生成树中 ...

  4. poj 2965 The Pilots Brothers' refrigerator (dfs)

    The Pilots Brothers' refrigerator Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17450 ...

  5. POJ 3321 树状数组(+dfs+重新建树)

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27092   Accepted: 8033 Descr ...

  6. POJ 3009 Curling 2.0 回溯,dfs 难度:0

    http://poj.org/problem?id=3009 如果目前起点紧挨着终点,可以直接向终点滚(终点不算障碍) #include <cstdio> #include <cst ...

  7. POJ 1426 Find The Multiple --- BFS || DFS

    POJ 1426 Find The Multiple 题意:给定一个整数n,求n的一个倍数,要求这个倍数只含0和1 参考博客:点我 解法一:普通的BFS(用G++能过但C++会超时) 从小到大搜索直至 ...

  8. poj 1564 Sum It Up (DFS+ 去重+排序)

    http://poj.org/problem?id=1564 该题运用DFS但是要注意去重,不能输出重复的答案 两种去重方式代码中有标出 第一种if(a[i]!=a[i-1])意思是如果这个数a[i] ...

  9. poj 1979 Red and Black(dfs水题)

    Description There is a rectangular room, covered with square tiles. Each tile is colored either red ...

随机推荐

  1. C 中 关于printf 函数中度剖析

    题外话  这篇博文主要围绕printf函数分析的,主要讲解printf 使用C的可变参数机制, printf是否可重入(是否线程安全), printf函数的源码实现. 正文 1.C中可变参数机制 我们 ...

  2. C/C++ 内存管理 (《高质量C++》-- 整理笔记)

    内存管理是我们在编程时经常遇到的问题,而关于内存管理的问题往往会导致我们无从下手,这篇随笔是我阅读<高质量C++>第7章“内存管理”时一些总结. 1.内存分配方式 在C++中内存分为5个区 ...

  3. mybatis数据库基本配置包括数据源事物类型等

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC ...

  4. hdu 5199 Gunner

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5199 简单题,stl水之... #include<algorithm> #include& ...

  5. 编写可维护的JavaScript之简易模版

    /* * 正则替换%s * @para arg1(text) 需要替换的模版 * @para arg2 替换第一处%s * @para arg3 替换第二处%s * 返回替换后的字符串 */ var ...

  6. php正则表达式获取表格内容

    <?php $contents = '<tr class=""> <td>508982</td> <td>08,07,01,0 ...

  7. sharepoint 2010 中获取system账号的真实账号

    在使用sharepoint的时候有的时候需要在后台获取当前登录用户的登录名,一般的时候使用SPContext.Current.Web.CurrentUser就可以了,但是有一个特殊的用“系统账户”,获 ...

  8. verilog运算符及表达式

    1.运输符 算术运算符(+,-,X,/,%) 赋值运算符(=,<=) 关系运算符(>,<,>=,<=) 逻辑运算符(&&,||,!)//与或非 条件运算符 ...

  9. KinectStudio使用教程

    在Kinect SDK 2.0安装结束之后,会有一个KinectStudio的调试工具,他可以将动作记录下,以后即便脱离了Kinect传感器也可以愉快的调试了.现在我们来看看如何使用 首先打开Kine ...

  10. windows+nginx+fcgi配置

    最近项目要求要学习一下nginx的知识,由于自己学疏才浅,搞了一天多终于基本搭建出来了,怕日后忘记,所以在此记录一下 nginx的历史,应用和种种就不记录了,自行百度.....Fcgi 相比cgi的好 ...