POJ-3294 Life Forms n个字符串中出现超过n/2次的最长子串(按字典序依次输出)

 按照以前两个字符串找两者的最长公共子串的思路类似,可以把所有串拼接到一起,这里为了避免讨论LCP跨越多个串需需要特别处理的问题用不同的字符把所有串隔开(因为char只有128位,和可能不够用,更推荐设置成某一特殊字符,在后缀数组初始化的时候在对其映射的int值做处理)。二分长度然后遍历Height,判断SA是否处于同一个串。这里我一开始觉得判断不同串的计数有点麻烦,其实根据LCP确定起点,随终点延伸Height值不会上升的特性,一旦Height小于我们要求的值就切换到下一计数(因为必然不可能再和之前计数的串再产生重合了)。

#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstdio>
#define debug puts("debug")
#define LL long long
using namespace std;

const int N=111005;
string s,temp;
int nn;
int pos[N];
int vis[N];
int phs[N];
int endp[N];
int stx[N],sp;


class SF
{
    //N:数组大小
public:
    int x[N], y[N], c[N];
    int Height[N], str[N], SA[N], Rank[N];//Height数组从2开始,SA记录Rank=i的下标
    int slen;
    int m;//字符集处理大小(传入如果不是数字,需要做位移转换)
    bool cmp(int* r, int a, int b, int l)
    {
        return r[a] == r[b] && r[a + l] == r[b + l];
    }
    void Suffix(int n)
    {
        ++n;
        int i, j, p;
        for (i = 0; i < m; ++i) c[i] = 0;
        for (i = 0; i < n; ++i) c[x[i] = str[i]]++;
        for (i = 1; i < m; ++i) c[i] += c[i - 1];
        for (i = n - 1; i >= 0; --i) SA[--c[x[i]]] = i;

        for (j = 1; j <= n; j <<= 1)
        {
            p = 0;
            for (i = n - j; i < n; ++i) y[p++] = i;
            for (i = 0; i < n; ++i) if (SA[i] >= j) y[p++] = SA[i] - j;
            for (i = 0; i < m; ++i) c[i] = 0;
            for (i = 0; i < n; ++i) c[x[y[i]]]++;

            for (i = 1; i < m; ++i) c[i] += c[i - 1];
            for (i = n - 1; i >= 0; --i) SA[--c[x[y[i]]]] = y[i];

            swap(x, y);
            p = 1;
            x[SA[0]] = 0;
            for (i = 1; i < n; ++i)
            {
                x[SA[i]] = cmp(y, SA[i - 1], SA[i], j) ? p - 1 : p++;
            }
            if (p >= n)break;
            m = p;
        }

        int k = 0;
        n--;
        for (i = 0; i <= n; ++i) Rank[SA[i]] = i;

        for (i = 0; i < n; ++i)
        {
            if (k)--k;
            j = SA[Rank[i] - 1];
            while (str[i + k] == str[j + k])++k;
            Height[Rank[i]] = k;
            //cout << k << endl;
        }
    }
    static const int bitlen = 35;
    LL lg2(LL p)//计算log2(n)
    {
        return (LL)(log(p) / log(2));
    }
    LL dp[bitlen][N];
    LL bit[bitlen];
    void initRMQ()//初始化
    {
        bit[0] = 1;
        for (int i = 1; i < bitlen; i++) bit[i] = 2 * bit[i - 1];
        for (int i = 0; i <= slen; i++)
            dp[0][i] = Height[i];
        dp[0][0] = dp[0][1] = 0;
        for (LL i = 1; bit[i] < slen + 1; i++)
            for (LL j = 0; j + bit[i] <= slen + 1; j++)
                dp[i][j] = min(dp[i - 1][j], dp[i - 1][j + bit[i - 1]]);
    }
    LL query(LL l, LL r)//查询两个Rank之间的lcp
    {
        if (r == l) return slen - SA[l];
        if (l > r) swap(l, r);
        l++;
        LL mig = lg2(r - l + 1.0);
        return min(dp[mig][l], dp[mig][r - bit[mig] + 1]);
    }
    void init(string s)
    {
        slen = s.size();
        m=1050;//每次都需要初始化m
        int fuck=1;
        for (int i = 0; i < slen; i++)
        {
            if(s[i]!='#')
                str[i] = s[i] - 'a' + 2;//如果是字符,映射成从1开始的序列
            else str[i]=100+(fuck++);
        }
        str[slen] = 0;//1作为结束符,防止越界
        Suffix(slen);

        initRMQ();
    }
    bool ok(int lx)
    {
        sp=0;
        fill(vis,vis+slen+1,0);
        int cnt=1;
        vis[phs[SA[1]]]=1;
        //cout<<phs[1]<<endl;
        for(int i=2; i<=slen; i++)
        {
            //cout<<Height[i]<<endl;
            //cout<<phs[i]<<endl;
            if(Height[i]>=lx)
            {
                if(vis[phs[SA[i]]]==0)
                    cnt++,vis[phs[SA[i]]]=1;
            }
            else
            {
                if(cnt>nn/2)
                    stx[sp++]=SA[i-1];
                cnt=1;
                fill(vis,vis+nn+1,0);
                vis[phs[SA[i]]]=1;
            }
        }
        if(cnt>nn/2)
            stx[sp++]=SA[slen-1];
        return sp;
    }
    int bins(int l,int r)
    {
        while(r-l>=3)
        {
            int mid=(l+r)/2;
            if(ok(mid))l=mid;
            else r=mid-1;
        }
        //cout<<l<<' '<<r<<endl;
        for(; r>=l; r--)
        {
            //cout<<r<<endl;
            if(ok(r))return r;
        }
        return 0;
    }

    void solve()
    {
        int f=bins(1,slen);
        if(!f)cout<<"?"<<endl;
        else
        {
            //sort(stx,stx+f,cmp);
            for(int i=0; i<sp; i++)
            {
                //cout<<stx[i]<<endl;
                for(int j=0; j<f; j++)
                    cout<<s[stx[i]+j];
                cout<<endl;
            }
        }
    }
} sf;
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    cin.sync_with_stdio(false);
    int cnt=0;
    while(cin>>nn)
    {
        if(!nn)break;
        if(cnt++)cout<<endl;
        s="";

        for(int i=0; i<nn; i++)
        {
            cin>>temp;
            pos[i]=temp.length();
            s+=temp;
            s+='#';
        }
        if(nn==1)
        {
            s=s.substr(0,s.length()-1);
            cout<<s<<endl;
            continue;
        }
        int p=0;
        for(int i=0; i<nn; i++)
        {
            for(int j=0; j<pos[i]; j++,p++)
                phs[p]=i;
            phs[p++]=nn;
            if(i==0)endp[i]=pos[i];
            else endp[i]=endp[i-1]+pos[i]+1;
        }
        sf.init(s);

        sf.solve();
        //sf.ok(1);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/LukeStepByStep/p/7883047.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
未来社区的建设背景和需求分析指出,随着智能经济、大数据、人工智能、物联网、区块链、云计算等技术的发展,社区服务正朝着数字化、智能化转型。社区服务渠道由分散向统一融合转变,服务内容由通用庞杂向个性化、服务导向转变。未来社区将构建数字化生态,实现数据在线、组织在线、服务在线、产品智能和决策智能,赋能企业创新,同时注重人才培养和科研平台建设。 规划设计方面,未来社区将基于居民需求,打造以服务为心的社区管理模式。通过统一的服务平台和应用,实现服务内容的整合和优化,提供灵活多样的服务方式,如推送式、订阅式、热点式等。社区将构建数据与应用的良性循环,提高服务效率,同时注重生态优美、绿色低碳、社会和谐,以实现幸福民生和产业发展。 建设运营上,未来社区强调科学规划、以人为本,创新引领、重点突破,统筹推进、整体提升。通过实施院落+社团自治工程,转变政府职能,深化社区自治法制化、信息化,解决社区治理的重点问题。目标是培养有活力的社会组织,提高社区居民参与度和满意度,实现社区治理服务的制度机制创新。 未来社区的数字化解决方案包括信息发布系统、服务系统和管理系统。信息发布系统涵盖公共服务类和社会化服务类信息,提供政策宣传、家政服务、健康医疗咨询等功能。服务系统功能需求包括办事指南、公共服务、社区工作参与互动等,旨在提高社区服务能力。管理系统功能需求则涉及院落管理、社团管理、社工队伍管理等,以实现社区治理的现代化。 最后,未来社区建设注重整合政府、社会组织、企业等多方资源,以提高社区服务的效率和质量。通过建立社区管理服务综合信息平台,提供社区公共服务、社区社会组织管理服务和社区便民服务,实现管理精简、高效、透明,服务快速、便捷。同时,通过培育和发展社区协会、社团等组织,激发社会化组织活力,为居民提供综合性的咨询和服务,促进社区的和谐发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值