题意:给出一系列字符串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(后缀数组)相关推荐

  1. 寻找一个字符串的重复子串 后缀数组

    什么是后缀数组 令字符串 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 ...

  2. 【2012百度之星/资格赛】H:用户请求中的品牌 [后缀数组]

    时间限制: 1000ms 内存限制: 65536kB 描述 馅饼同学是一个在百度工作,做用户请求(query)分析的同学,他在用户请求中经常会遇到一些很奇葩的词汇.在比方说"johnsonj ...

  3. Boring counting HDU - 3518 (后缀数组)

    Boring counting \[ Time Limit: 1000 ms \quad Memory Limit: 32768 kB \] 题意 给出一个字符串,求出其中出现两次及以上的子串个数,要 ...

  4. HDU4080 Stammering Aliens(二分 + 后缀数组)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4080 Description Dr. Ellie Arroway has establish ...

  5. 后缀数组 + Hash + 二分 or Hash + 二分 + 双指针 求 LCP ---- 2017icpc 青岛 J Suffix (假题!!)

    题目链接 题目大意: 就是给你n个串每个串取一个后缀,要求把串拼起来要求字典序最小!! sum_length_of_n≤5e5sum\_length\_of\_n\leq 5e5sum_length_ ...

  6. 后缀数组 ---- 2018~2019icpc焦作H题[后缀数组+st表+二分+单调栈]

    题目链接 题目大意: 给出nnn个数,定义f[l,r]f[l,r]f[l,r]表示 区间[l,r][l,r][l,r]的最大值,求所有 子区间的最大值的和,要求相同的子区间只能算一次 比如数列 5 6 ...

  7. [Ahoi2013]差异[后缀数组+单调栈]

    链接 解题思路:很明显前面∑1<=i<j<=nlen(Ti)+len(Tj)\sum_{1<=i<j<=n}len(T_i)+len(T_j)∑1<=i< ...

  8. poj2217详解 ( 后缀数组 + 高度数组 )

    题目大概意思就是 给两个字符串,求最长公共字符串子串长度 我们可以考虑用后缀数组和高度数组 一个字符串 中 最长的两个相同字符串长度, 不就是 后缀数组中相邻两个后缀的最长公共前缀, 不就是 高度数组 ...

  9. 树链剖分 + 后缀数组 - E. Misha and LCP on Tree

    E. Misha and LCP on Tree Problem's Link Mean: 给出一棵树,每个结点上有一个字母.每个询问给出两个路径,问这两个路径的串的最长公共前缀. analyse: ...

最新文章

  1. java if else 过多_Java中if-else过多怎么解决
  2. 汇编语言学习笔记(五)
  3. DVA框架统一处理所有页面的loading状态
  4. Android (AMS)ActivityManagerService源码分析
  5. 【总结】6种机器学习中的优化算法:SGD,牛顿法,SGD-M,AdaGrad,AdaDelta,Adam
  6. I LOVE YOU TOO密码解析
  7. 创业公司必备,20个提升团队工作效率的工具神器
  8. php temp 删除,c盘temp文件夹可以删除吗
  9. 正好配资点评北交所成立,新基建起爆
  10. 安装MySQL过程中,出现“Staring the server”错误的解决方法
  11. 子网掩码的作用和用法
  12. ue4 unreal NDisplay插件 简易使用 三折幕 详细...
  13. 【matlab】正弦波、方波、三角波、白噪声等8种基本信号
  14. 数据标准化与PCA白化原理探索
  15. SystemVerilog学习笔记(可综合的部分)(一)
  16. 【ceph相关】ceph基准性能测试工具
  17. 盲目入手餐饮业并不可取,三思而后行极为关键
  18. DTC趋势 | 2022年值得关注的10个DTC趋势
  19. 网络类型(hcip)
  20. 基于matlab Simulink的双闭环三相和五相永磁同步电机仿真模型

热门文章

  1. 熟练掌握python是什么概念-想要熟练掌握Python元组?你需要了解这10件应知事项...
  2. python语言是一种高级通用编程语言-2019年十大顶级编程语言:会这些的程序员薪资有多高?...
  3. python导入csv文件-Python从CSV文件导入数据和生成简单图表
  4. python手机版iphone-只会Python可造不出iPhone
  5. 案例驱动python编程入门-python ddt数据驱动实例代码分享
  6. python利器怎么编程-Linux 利器- Python 脚本编程入门(一)
  7. python读取大文件-Python如何读取、拆分大文件
  8. python画折线图详解-python如何画折线图
  9. python turtle画气球-气球排列
  10. python语言if语句-Python2 if 条件语句