算法问题实战策略 DICTIONARY

地址 https://algospot.com/judge/problem/read/DICTIONARY

解法 构造一个26字母的有向图 判断无回路后 就可以输出判断出来的字符序了

比较各个字母的先后次序不必用一个单词分别同其他单词比较 只需要将临近的两个单词一一比较即可

证明如下

算法1 中判断有无回路 采取的是DFS方法

代码

  1 #include <iostream>
  2 #include <string>
  3 #include <vector>
  4 #include <algorithm>
  5 #include <memory.h>
  6
  7 using namespace std;
  8
  9 /*
 10 3
 11 3
 12 ba
 13 aa
 14 ab
 15 5
 16 gg
 17 kia
 18 lotte
 19 lg
 20 hanhwa
 21 6
 22 dictionary
 23 english
 24 is
 25 ordered
 26 ordinary
 27 this
 28 ======================================================
 29 INVALID HYPOTHESIS
 30 ogklhabcdefijmnpqrstuvwxyz
 31 abcdefghijklmnopqrstuvwxyz
 32 */
 33
 34 int n;
 35
 36 vector<pair<int, int>> vvmap;
 37
 38 void Compare(string s1, string s2)
 39 {
 40     int len = min(s1.size(),s2.size());
 41
 42     for (int i = 0; i < len; i++) {
 43         if (s1[i] == s2[i]) continue;
 44         int a = s1[i] - ‘a‘;
 45         int b = s2[i] - ‘a‘;
 46         vvmap.push_back({a,b});
 47         break;
 48     }
 49 }
 50
 51
 52 vector<int>  seen, order;
 53
 54 void dfs(int here) {
 55     seen[here] = 2;
 56     for (int there = 0; there < 26; ++there) {
 57         if ( find(vvmap.begin(),vvmap.end(),pair<int,int>(here,there)) != vvmap.end()
 58                     && seen[there] == 1 )
 59             dfs(there);
 60     }
 61     order.push_back(here);
 62 }
 63
 64 vector<int> topologicalSort()
 65 {
 66     seen = vector<int>(26, 0);
 67     for (int i = 0; i < vvmap.size(); i++) {
 68         //记录需要dfs的索引
 69         if (seen[vvmap[i].first] == 0)
 70             seen[vvmap[i].first] =1;
 71         if (seen[vvmap[i].second] == 0)
 72             seen[vvmap[i].second] = 1;
 73     }
 74     order.clear();
 75     for (int i = 0; i <  26; i++) {
 76         if (seen[i] == 1)
 77             dfs(i);
 78     }
 79
 80     reverse(order.begin(), order.end());
 81
 82     for (int i = 0; i < order.size(); i++) {
 83         for (int j = i+1; j < order.size(); j++) {
 84             if (find(vvmap.begin(), vvmap.end(), pair<int, int>(order[j], order[i])) != vvmap.end())
 85             {
 86                 return vector<int>();
 87             }
 88         }
 89     }
 90     return order;
 91 }
 92
 93
 94 int main()
 95 {
 96     cin >> n;
 97
 98     while (n--) {
 99         int m;
100         vvmap.clear();
101         cin >> m;
102         vector<string> vs;
103         for (int i = 0; i < m; i++) {
104             string s;
105             cin >> s;
106             vs.push_back(s);
107         }
108
109         for (int i = 0; i < vs.size()-1; i++) {
110             Compare(vs[i], vs[i + 1]);
111         }
112
113         vector<int> ans = topologicalSort();
114         if (ans.empty()) {
115             cout << "INVALID HYPOTHESIS" << endl;
116         }
117         else {
118             for (int i = 0; i < 26; i++) {
119                 if (find(ans.begin(), ans.end(), i) == ans.end()) {
120                     ans.push_back(i);
121                 }
122             }
123
124             for (int i = 0; i < ans.size(); i++) {
125                 cout << (char)(ans[i] + ‘a‘);
126             }
127             cout << endl;
128         }
129     }
130
131 }

还可以以找欧拉回路的方法 判断字符序是否有无回路

todo

原文地址:https://www.cnblogs.com/itdef/p/11749808.html

时间: 2024-10-10 16:25:01

算法问题实战策略 DICTIONARY的相关文章

《算法问题实战策略》-chaper7-穷举法

关于这一章节<算法实战策略>有一段概述问题,我认为对于编程人员来说非常有价值,故在这里进行如下的摘抄: 构想算法是很艰难的工作.相比大家都经历过,面对复杂的要求只是傻乎乎地盯着显示器,或者不经过深思熟虑就开始打键盘,结果还要辛辛苦苦修改变得一塌糊涂的代码.经过这些磨难,各位就能切身体会到设计算法的重要性. 与通常所想不同,支配设计算法的并不是一时的灵感,而是许多策略性的选择.构想算法不仅需要理解问题的特性,还要理解执行时间和占用内存空间之间的对立关系,而且要会选择适当的数据结构. 算法设计范式

《算法问题实战策略》-chaper32-网络流

基本的网络流模型: 在图论这一块初步的应用领域中,两个最常见的关注点,其一时图中的路径长度,也就是我们常说的的最短路径问题,另一个则是所谓的“流问题”. 流问题的基本概念: 首先给出一张图. 其实所谓“网络流”,其模型是非常有现实意义的.我们将该图视为计算机网络结构.此图中,s称其为源点而t称其为汇点.这个图中剩余的源泉代表网络设备,连接个顶点的边线表示连接两个设备的数据线缆,边的权值表示这条线缆能够传输的最大数据. 首先我们应该能够注意到,有向路径<s,t>就是一条传输路线,而这条传输数据的

《算法问题实战策略》——chaper9——动态规划法技巧

Q1: 数字游戏: 两个人(A.B)用n个整数排成的一排棋盘玩游戏,游戏从A开始,每个人有如下操作: (1)    拿走棋盘最右侧或者最左侧的棋子,被拿走的数字从棋盘中抹掉. (2)    棋盘中还剩下两个以上的数字的时候,可以把棋盘最右侧或者最左侧的两个数字抹掉 当棋盘上的所有数字消失之后,游戏结束,谁拿的棋子代表的整数之和较大谁赢,现在假设两个游戏者都是聪明的,给出长度为n的序列,请计算游戏结束之后A的分数和B的分数的差值. 分析:其实相似的问题在<训练指南>当中曾经分析过,那个题目叫做“

《算法问题实战策略》-chaper21-树的实现和遍历

这一章节开始介绍一个数据结构中的一个基本概念——树. 我们从数据结构的解读来解释树结构的重要性,现实世界的数据除了最基本的线性结构(我们常用队列.数组和链表等结构表征),还有一个重要的特性——层级结构需要我们去表征,例如世界杯的对阵表.遗传系谱图等等,这时候我们基于对现实世界的抽象,会很自然的理解为什么会有树这样一个数据结构. 而树这种数据结构也是能够分类的,我们将每个节点记录某种抽象的概念或者具象的事物,这样用来表征一种从属关系,我们称其为抽象型数据结构的树.或者将每个节点储存一些数据,基于这

《算法问题实战策略》-chaper13-数值分析

这一章节主要介绍我们在进行数值分析常用的二分.三分策略. 首先介绍二分. 其实二分的思想很好理解并且笔者在之前的一些文章中也有所渗透,对于二次函数甚至单元高次函数的零点求解.线段树还有<algorithm puzzle>当中的“切割钢条”问题,都是基于二分思想. 下面我们通过具体的问题来应用二分这种数值分析的策略. Ex1:按揭贷款 以P%的年利率借贷N元后,在M个月内,以每月还C元的方式还贷.贷款期限内,按照如下形式计算贷款余额. (1)    贷款余额从余额N元开始. (2)    美国一

算法问题实战策略 QUADTREE

地址 https://algospot.com/judge/problem/read/QUADTREE 将压缩字符串还原后翻转再次压缩的朴素做法 在数据量庞大的情况下是不可取的 所以需要在压缩的情况下进行翻转 图片可以分成四块 每块在颜色不统一的情况下又会分成四块 那么翻转也可以采取这种逐步将问题分解成小块翻转 然后再处理大块算法 最后的到结果的算法 代码如下 #include <iostream> #include <string> using namespace std; /*

算法问题实战策略 MEETINGROOm

地址 解答 todo 错误代码 1 // Tarjan_Scc.cpp : 此文件包含 "main" 函数.程序执行将在此处开始并结束. 2 // 3 4 #include "pch.h" 5 6 7 #include <algorithm> 8 #include <iostream> 9 #include <vector> 10 #include <stack> 11 12 using namespace std;

《算法问题实战策略》-chaper14-整数论

Lucas定理: 在组合计数问题中,我们常面临组合数C(n,m)过大而无法直接计算的困境,那么这里的Lucas定理给出了一个较大组合数进行取余运算的一种递归算法. 什么是Lucas定理? Lucas定理的推导证明? 这个推导过程基于二项式定理,基于最后的等式,我们通过过找等是左边和右边x^(tp + r)的系数,即可完成对Lucas定理的证明.但是这里并没有呈现对p为什么是素数的说明. 在这里我们给出Lucas定理的另外一种表达形式: 我个人认为,限定了取模的数p是素数,这样统一了运算,即对于∏

《算法问题实战策略》-chaper15-计算几何-线段相交

这篇文章着力来讨论线段相交这一个问题. 给出两条线段,如何判断这两条线段相交? 如果这两条线段相交,如何求其交点? 线段相交问题通常由于其繁杂的情况种类而让人避而远之,在这里希望通过笔者的简化讨论希望帮读者的思路进行一下梳理. 首先我们尝试画几个几何图像来找一下线段相交的一些不同的情况,这里需要注意,可能有读者会好奇,这些直观上来看没什么差别的相交情况,我们为什么为认为他们是不同的呢?答案是,这里我们需要将几何特征用代数表达是进行判断,因此不同的几何特征虽然都表示线段相交,但是对应的代数表达式不