UVa11107 - Life Forms(后缀数组)
题意:给出一系列字符串s1,s2,s3,...sn,求最长的子串,要求在n/2一半以上的字符串中出现
思路:构造后缀数组,然后根据长度作二分查找,看是否在一半以上的字符串中出现
代码如下:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <climits>
#include <algorithm>
#include <cstring>
#include <set>
#include <iterator>using namespace std;const int MAXN = 100100;
const int N = 260;
const int M = 360;int str[MAXN];class SuffixArray
{
public:SuffixArray(int* pa, int n);~SuffixArray();void buildSa();void buildHeight();const int* getSa();const int* getHeight();
private:int *m_prank;int *m_pheight;int *m_psa;int m_n;int* m_a;
};SuffixArray::SuffixArray(int* pa, int n):m_prank(NULL), m_pheight(NULL), m_psa(NULL)
{m_a = pa;m_n = n;
}SuffixArray::~SuffixArray()
{delete []m_prank;delete []m_psa;delete []m_pheight;
}void SuffixArray::buildSa()
{m_prank = new int[m_n];int n = max(M, m_n);int* tmp = new int[m_n];int* c = new int[n];m_psa = new int[m_n];m_pheight = new int[m_n];memset(c, 0, sizeof(int) * n);for (int i = 0; i < m_n; i++){m_prank[i] = m_a[i];c[m_prank[i]]++;}for (int i = 1; i < n; i++){c[i] += c[i - 1];}for (int i = m_n - 1; i >= 0; i--){m_psa[--c[m_prank[i]]] = i;}int m = m_n;for (int i = 1; i <= m_n; i <<= 1) {int p = 0;for (int j = m_n - i; j < m_n; j++){tmp[p++] = j;}for (int j = 0; j < m_n; j++){if (m_psa[j] >= i){tmp[p++] = m_psa[j] - i;}}memset(c, 0, sizeof(int) * n);for (int j = 0; j < m_n; j++){c[m_prank[tmp[j]]]++;}for (int j = 1; j < n; j++){c[j] += c[j - 1];}for (int j = m_n - 1; j >= 0; j--){m_psa[--c[m_prank[tmp[j]]]] = tmp[j];}swap(m_prank, tmp);m_prank[m_psa[0]] = 0;m = 0;for (int j = 1; j < m_n; j++){if (tmp[m_psa[j - 1]] == tmp[m_psa[j]] && m_psa[j- 1] + i < m_n && m_psa[j] + i < m_n && tmp[m_psa[j - 1] + i] == tmp[m_psa[j] + i]){m_prank[m_psa[j]] = m;}else {m_prank[m_psa[j]] = ++m;}}if (m >= m_n - 1) break;}delete []c;delete []tmp;return;
}void SuffixArray::buildHeight()
{m_pheight[0] = 0;int k = 0;for (int i = 0; i < m_n; i++){int curPos = m_prank[i];if (curPos == 0) continue;curPos--;int j = m_psa[curPos];if (k){k--;}while (i + k < m_n && j + k < m_n && m_a[i + k] == m_a[j + k]) k++;m_pheight[m_prank[i]] = k;}
}const int* SuffixArray::getSa()
{return m_psa;
}const int* SuffixArray::getHeight()
{return m_pheight;
}bool check(vector<set<int> >& v, const int* pa, int pan, vector<string>& vecStr);
int checkPos(int sa, vector<string>& vecStr);
vector<set<int> > getSeg(const int* psa, const int *pheight, int n, int mid);
vector<string> getAns(vector<set<int> >& v, const int* pa, int pan, vector<string>& vecStr, int len, int* pStr, int strLen);int main(int argc, char **argv)
{
#ifndef ONLINE_JUDGEifstream fin("f:\\OJ\\uva_in.txt");ofstream fout("f:\\OJ\\uva_out.txt");streambuf* oldcin = cin.rdbuf(fin.rdbuf());streambuf* oldcout = cout.rdbuf(fout.rdbuf());
#endifint n;string s;int testCase = 0;while (cin >> n){if (0 == n){break;}getline(cin, s);vector<string> vecStr;int strLen = 0;for (int i = 0; i < n; i++){getline(cin, s);vecStr.push_back(s);int sLen = s.length();for (int j = 0; j < sLen; j++){str[strLen++] = s[j];}str[strLen++] = N + i;}SuffixArray sa(str, strLen);sa.buildSa();sa.buildHeight();const int* psa = sa.getSa();const int* pheight = sa.getHeight();int maxLen = INT_MAX;for (int i = 0, vecStrSize = vecStr.size(); i < vecStrSize; i++){maxLen = min(maxLen, static_cast<int>(vecStr[i].size()));}int l = 0, r = maxLen + 1;while (l < r){int mid = (l + r) >> 1;vector<set<int> > seg = getSeg(psa, pheight, strLen, mid);bool ok = check(seg, psa, strLen, vecStr);if (ok){l = mid + 1;}else{r = mid;}}if (testCase++){cout << endl;}if (1 == n){cout << vecStr[0] << endl;continue;}if (0 == l){cout << "?" << endl;}else{vector<set<int> > seg = getSeg(psa, pheight, strLen, l - 1);vector<string> ans = getAns(seg, psa, strLen, vecStr, l - 1, str, strLen);sort(ans.begin(), ans.end());for (size_t i = 0, ansSize = ans.size(); i < ansSize; i++){cout << ans[i] << endl;}}}#ifndef ONLINE_JUDGEcin.rdbuf(oldcin);cout.rdbuf(oldcout);
#endif
}bool check(vector<set<int> >& v, const int* pa, int pan, vector<string>& vecStr)
{for (size_t i = 0; i < v.size(); i++){set<int> &intSet = v[i];bool *flag = new bool[vecStr.size()];memset(flag, false, sizeof(bool) * (int)vecStr.size());for (set<int>::iterator it = intSet.begin(); it != intSet.end(); it++){int sa = pa[*it];int retVal = checkPos(sa, vecStr);if (0 <= retVal){flag[retVal] = true;}}int cnt = 0;for (size_t i = 0, vecStrSize = vecStr.size(); i < vecStrSize; i++){if (flag[i]){cnt++;}}delete []flag;if (cnt > (int)vecStr.size() / 2){return true;}}return false;
}int checkPos(int sa, vector<string>& vecStr)
{for (size_t i = 0, vecStrSize = vecStr.size(); i < vecStrSize; i++){if (sa > (int)vecStr[i].size()){sa -= vecStr[i].size() + 1;}else if (sa == (int)vecStr[i].size()){return -1;}else{return i;}}return -1;
}vector<set<int> > getSeg(const int* psa, const int *pheight, int n, int mid)
{vector<set<int> > seg;set<int> intSet;intSet.insert(0);for (int i = 1; i < n; i++){if (mid > 0 && pheight[i] >= mid && memcmp((const void*)&str[psa[i - 1]], (const void*)&str[psa[i]], sizeof(int) * pheight[i]) == 0){intSet.insert(i);}else{seg.push_back(intSet);intSet.clear();intSet.insert(i);}}if (!intSet.empty()){seg.push_back(intSet);}return seg;
}vector<string> getAns(vector<set<int> >& v, const int* pa, int pan, vector<string>& vecStr, int len, int* pStr, int strLen)
{vector<string> ans;for (size_t i = 0; i < v.size(); i++){set<int> &intSet = v[i];bool *flag = new bool[vecStr.size()];memset(flag, false, sizeof(bool) * (int)vecStr.size());for (set<int>::iterator it = intSet.begin(); it != intSet.end(); it++){int sa = pa[*it];int retVal = checkPos(sa, vecStr);if (0 <= retVal){flag[retVal] = true;}}int cnt = 0;for (size_t i = 0, vecStrSize = vecStr.size(); i < vecStrSize; i++){if (flag[i]){cnt++;}}delete []flag;if (cnt > (int)vecStr.size() / 2){int sa = pa[*intSet.begin()];string s;for (int i = sa; i < sa + len; i++){s += (char)pStr[i];}ans.push_back(s);}}return ans;
}
UVa11107 - Life Forms(后缀数组)相关推荐
- 寻找一个字符串的重复子串 后缀数组
什么是后缀数组 令字符串 S=S[1]S[2]...S[n]S=S[1]S[2]...S[n]{\displaystyle S=S[1]S[2]...S[n]} , S[i,j]S[i,j]{\dis ...
- 【2012百度之星/资格赛】H:用户请求中的品牌 [后缀数组]
时间限制: 1000ms 内存限制: 65536kB 描述 馅饼同学是一个在百度工作,做用户请求(query)分析的同学,他在用户请求中经常会遇到一些很奇葩的词汇.在比方说"johnsonj ...
- Boring counting HDU - 3518 (后缀数组)
Boring counting \[ Time Limit: 1000 ms \quad Memory Limit: 32768 kB \] 题意 给出一个字符串,求出其中出现两次及以上的子串个数,要 ...
- HDU4080 Stammering Aliens(二分 + 后缀数组)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4080 Description Dr. Ellie Arroway has establish ...
- 后缀数组 + Hash + 二分 or Hash + 二分 + 双指针 求 LCP ---- 2017icpc 青岛 J Suffix (假题!!)
题目链接 题目大意: 就是给你n个串每个串取一个后缀,要求把串拼起来要求字典序最小!! sum_length_of_n≤5e5sum\_length\_of\_n\leq 5e5sum_length_ ...
- 后缀数组 ---- 2018~2019icpc焦作H题[后缀数组+st表+二分+单调栈]
题目链接 题目大意: 给出nnn个数,定义f[l,r]f[l,r]f[l,r]表示 区间[l,r][l,r][l,r]的最大值,求所有 子区间的最大值的和,要求相同的子区间只能算一次 比如数列 5 6 ...
- [Ahoi2013]差异[后缀数组+单调栈]
链接 解题思路:很明显前面∑1<=i<j<=nlen(Ti)+len(Tj)\sum_{1<=i<j<=n}len(T_i)+len(T_j)∑1<=i< ...
- poj2217详解 ( 后缀数组 + 高度数组 )
题目大概意思就是 给两个字符串,求最长公共字符串子串长度 我们可以考虑用后缀数组和高度数组 一个字符串 中 最长的两个相同字符串长度, 不就是 后缀数组中相邻两个后缀的最长公共前缀, 不就是 高度数组 ...
- 树链剖分 + 后缀数组 - E. Misha and LCP on Tree
E. Misha and LCP on Tree Problem's Link Mean: 给出一棵树,每个结点上有一个字母.每个询问给出两个路径,问这两个路径的串的最长公共前缀. analyse: ...
最新文章
- java if else 过多_Java中if-else过多怎么解决
- 汇编语言学习笔记(五)
- DVA框架统一处理所有页面的loading状态
- Android (AMS)ActivityManagerService源码分析
- 【总结】6种机器学习中的优化算法:SGD,牛顿法,SGD-M,AdaGrad,AdaDelta,Adam
- I LOVE YOU TOO密码解析
- 创业公司必备,20个提升团队工作效率的工具神器
- php temp 删除,c盘temp文件夹可以删除吗
- 正好配资点评北交所成立,新基建起爆
- 安装MySQL过程中,出现“Staring the server”错误的解决方法
- 子网掩码的作用和用法
- ue4 unreal NDisplay插件 简易使用 三折幕 详细...
- 【matlab】正弦波、方波、三角波、白噪声等8种基本信号
- 数据标准化与PCA白化原理探索
- SystemVerilog学习笔记(可综合的部分)(一)
- 【ceph相关】ceph基准性能测试工具
- 盲目入手餐饮业并不可取,三思而后行极为关键
- DTC趋势 | 2022年值得关注的10个DTC趋势
- 网络类型(hcip)
- 基于matlab Simulink的双闭环三相和五相永磁同步电机仿真模型
热门文章
- 熟练掌握python是什么概念-想要熟练掌握Python元组?你需要了解这10件应知事项...
- python语言是一种高级通用编程语言-2019年十大顶级编程语言:会这些的程序员薪资有多高?...
- python导入csv文件-Python从CSV文件导入数据和生成简单图表
- python手机版iphone-只会Python可造不出iPhone
- 案例驱动python编程入门-python ddt数据驱动实例代码分享
- python利器怎么编程-Linux 利器- Python 脚本编程入门(一)
- python读取大文件-Python如何读取、拆分大文件
- python画折线图详解-python如何画折线图
- python turtle画气球-气球排列
- python语言if语句-Python2 if 条件语句