模板

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = 1500 + 10;
int n,x,y;
struct node {
    int xx,yy,id;
    bool operator < (const node &a) const {
        if(xx-x>=0 && a.xx-x<=0) return 1;
        if(xx-x<=0 && a.xx-x>=0) return 0;
        return (yy-y)*(ll)(a.xx-x)<(a.yy-y)*(ll)(xx-x);
    }
}p[M];

vector<int> g[M];
int sz[M];
int ans[M];

void dfs (int o,int u) {
    sz[u] = 1;
    for (int &v : g[u]) if (v!=o) {
        dfs (u, v);
        sz[u] += sz[v];
    }
}

void dfs2 (int o,int u,int l,int r) {
    if (sz[u]==1) {
        ans[p[l].id] = u;
        return;
    }
    int id=l;
    for (int i=l+1; i<r; ++i) {
        if (p[i].xx < p[id].xx) {
            id = i;
        }
    }
    swap(p[id], p[l]);
    ans[p[l].id] = u;
    x=p[l].xx, y=p[l].yy;
    sort (p+l+1, p+r);
    int sum = l+1;
    for (int &v : g[u]) if (v!=o) {
        dfs2 (u, v, sum, sum+sz[v]);
        sum += sz[v];
    }
}

int main () {
    scanf ("%d", &n);
    for (int i=1,u,v; i<n; ++i) {
        scanf ("%d%d", &u,&v);
        g[u].emplace_back(v);
        g[v].emplace_back(u);
    }
    for (int i=0; i<n; ++i) {
        scanf ("%d%d", &p[i].xx, &p[i].yy);
        p[i].id = i;
    }
    dfs (1, 1);
    dfs2 (1, 1, 0, n);
    for (int i=0; i<n; ++i) {
        printf ("%d%c", ans[i], " \n"[i==n-1]);
    }
    return 0;
}
极角排序

 

#include<bits/stdc++.h>
using namespace std;
const int M = 2000+10;
typedef vector<int> vec;
vec g[M];
vec rg[M];
vec vs;
bool used[M];
int cmp[M];
int n;

void dfs (int u) {
    used[u] = true;
    for (int &v : g[u]) if (!used[v]) {
        dfs (v);
    }
    vs.emplace_back(u);
}

void rdfs (int u,int k) {
    used[u] = true;
    cmp[u] = k;
    for (int &v : rg[u]) if (!used[v]) {
        rdfs (v, k);
    }
}

int scc() {
    memset (used, false, sizeof(used));
    vs.clear();
    for (int v=0; v<n; ++v) {
        if (!used[v]) dfs (v);
    }
    memset (used, 0, sizeof(used));
    int k = 0;
    for (int i=vs.size()-1; i>=0; --i) {
        if (!used[vs[i]]) rdfs (vs[i], k++);
    }
    //printf ("%d\n",k);
    return k;
}

int main () {
    scanf ("%d", &n);
    for (int i=0; i<n; ++i) {
        for (int j=0; j<n; ++j) {
            int x;
            scanf ("%d", &x);
            if (x) {
                g[i].emplace_back(j);
                rg[j].emplace_back(i);
            }
        }
    }
    printf ("%s\n", scc()==1?"YES" : "NO");
    return 0;
}
强联通

 

 1 vector<bool> isprime;
 2 vector<int> mu;
 3 void sieve () {
 4     isprime.assign(M, true);
 5     isprime[0] = isprime[1] = false;
 6     for (int i=2; i<M/i; ++i) if (isprime[i]) {
 7         for (int j=i*i; j<M; j+=i) {
 8             isprime[j] = false;
 9         }
10     }
11     mu.assign(M, 1);
12     for (int i=2; i<M; ++i) if (isprime[i]) {
13         if (i<M/i) {
14             for (int j=i*i; j<M; j+=i*i) mu[j] = 0;
15         }
16         for (int j=i; j<M; j+=i) mu[j] *= -1;
17     }
18 }
埃筛 && 莫比乌斯函数

 

import java.math.BigInteger;

import java.util.Scanner;

public class Main {

public static void main(String[] args) {
        Scanner cin=new Scanner(System.in);
        BigInteger a,b;

        BigInteger big1=BigInteger.ZERO;//0 声明一个大整数并常数值赋值0  
        BigInteger big2=BigInteger.ONE;//1  
        BigInteger big3=BigInteger.TEN;//10  
          
        BigInteger big4 =new BigInteger("1000");//赋除了0,1,10之外的常数值的方法一  
        BigInteger big5= BigInteger.valueOf(1000);//没有new赋除了之外的常数值的方法二  
        //BigInteger bi1 =  new BigInteger(55,new Random());  生成一个个随机的大整数  
          
        BigInteger [] f=new BigInteger [1005];//声明大整数数组,并赋值  
        f[1]=BigInteger.ZERO;  
        f[2]=BigInteger.ONE;  
        f[3]=f[2];  
        f[4]= BigInteger.valueOf(3);//a[4]=a[2].add(a[2].add(a[2]));  
        System.out.println(f[4]);  

        while(cin.hasNext()) {
            a=cin.nextBigInteger();
            b=cin.nextBigInteger();
            System.out.println(a.add(b));//输出a+b
            System.out.println(a.subtract(b));//输出a-b
            System.out.println(a.multiply(b));//输出a*b
            System.out.println(a.divide(b));//输出a/b
            System.out.println(a.remainder(b));//输出a%b
            if(a.compareTo(b)==0)System.out.println("a==b");
            if(a.compareTo(b)>0)System.out.println("a>b");
            if(a.compareTo(b)<0)System.out.println("a<b");
            System.out.println(a.abs());//大数a的绝对值
            int exponent=cin.nextInt();
            System.out.println(a.pow(exponent)); //大整数a的exponent次幂
             //返回大整数十进制的字符串表示
            System.out.println(a.toString());
            //返回大整数p进制的字符串表示
            int p=cin.nextInt();
            System.out.println(a.toString(p));
        }
    }
}
java BigInteger

 

import java.math.*;
import java.text.*;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner cin=new Scanner(System.in);
        int n;
        while(cin.hasNext())//等效于输入到文件尾
        {
            n = cin.nextInt();
            BigInteger fact = new BigInteger("1");
            BigInteger dp = new BigInteger("1");
            for (int i=2; i<=n; ++i) {
                dp = dp.multiply(BigInteger.valueOf(i)).add(fact);
                fact = fact.multiply(BigInteger.valueOf(i));
            }
            BigDecimal ans = new BigDecimal(dp);
            //BigInteger -> BigDecimal
            BigDecimal __fact = new BigDecimal(fact);
            //方法一
            //四舍五入到小数点后4位,格式“#.0000”
            DecimalFormat df = new DecimalFormat("#.0000");
            double zz = ans.divide(__fact,10, BigDecimal.ROUND_HALF_UP).doubleValue();
            System.out.println(df.format(zz));
            
            //方法二,全部输出
            //stripTrailingZeros() :用于去除末尾多余的0
            //toPlainString(): 控制不使用科学计数法输出
            System.out.println(ans.stripTrailingZeros().toPlainString());
        }
    }
}
BigDecimal

 

//注意:因为 sam 在头部插入了一个 nill 字符(如果没有nill,right集会少
//所以对于 parent树 的叶子:
//如果 l(leaf) == l(fa(leaf)) + 1, 那么说明实际上从 fa(leaf) -> leaf这条边实际上是通过走 nill 字符通过的,
//及原串实际上是不会走到这个节点的。
//hdu6194
#include<bits/stdc++.h>
using namespace std;
const int M = 1e5 + 10;
char s[M];

struct SAM {
    static const int kN = M << 1;
    static const int chN = 26;
    int fa[kN];
    int go[kN][chN];
    int l[kN];
    int o;
    int rt;
    int lst;

    inline int newNode(int _l) {
        for (int i=0; i<chN; ++i) {
            go[o][i] = -1;
        }
        l[o] = _l;
        return o ++;
    }
    void Init() {
        o = 0;
        rt = lst = newNode(0);
        fa[rt] = -1;
    }
    inline void InsKey() {
        int p = lst, np = newNode(l[lst]+1); lst = np;
        fa[np] = rt;
    }
    inline void Ins(int c) {
        int p = lst, np = newNode(l[lst]+1); lst = np;
        //printf ("%c:%d\n", c+'a', np);
        while (~p && go[p][c] == -1) go[p][c] = np, p = fa[p];
        if (p==-1) fa[np] = rt;
        else {
            int q = go[p][c];
            if (l[p]+1 == l[q]) fa[np] = q;
            else {
                int nq = newNode(l[p]+1);
                //printf ("%c:%d\n", c+'a', nq);
                memcpy(go[nq], go[q], sizeof(go[q]));
                fa[nq] = fa[q];
                fa[q] = fa[np] = nq;
                while (~p && go[p][c] == q) go[p][c] = nq, p = fa[p];
            }
        }
    }

    //topo
    int ord[kN];
    int cnt[kN];
    int right[kN];
    int in[kN];
    void topo() {
        int maxVal = 0;
        memset (cnt, 0, sizeof(cnt[0])*o);
        for (int i=0; i<o; ++i) maxVal = max(maxVal, l[i]), ++ cnt[l[i]];
        for (int i=1; i<=maxVal; ++i) cnt[i] += cnt[i-1];
        for (int i=0; i<o; ++i) ord[-- cnt[l[i]]] = i;
    }

    int solve(int k) {
        topo();
        memset (right, 0, sizeof(right[0])*o);
        memset (in, 0, sizeof(in[0])*o);
        for (int i=1; i<o; ++i) ++in[fa[i]];
        for (int i=1; i<o; ++i) right[i] = !in[i];
        for (int i=o-1; i>0; --i) right[fa[ord[i]]] += right[ord[i]];
        int ret = 0;
        for (int i=1; i<o; ++i) {
            if (k == right[i]) ret += l[i]-l[fa[i]]-(in[i]==0);
        }
        return ret;
    }
} sam;

int main () {
    int CASE;
    scanf ("%d", &CASE);
    while (CASE --) {
        int k;
        scanf ("%d%s", &k, s);
        sam.Init();
        sam.InsKey();
        for (int i=0; s[i]; ++i) {
            sam.Ins(s[i]-'a');
        }
        printf ("%d\n", sam.solve(k));
    }
    return 0;
}
sam

 

#include <stdio.h>
#include <numeric>
#include <time.h>
#include <bitset>
#include <string.h>
#include <stack>
#include <algorithm>
#include <iostream>
#include <set>
#include <map>
#include <math.h>
#include <queue>
#include <complex>
#include <functional>
#include <limits.h>
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef unsigned long long ull ;
#ifdef _WIN32
#define LLD "%I64d"
#else
#define LLD "%lld"
#endif
#define pi (acos(-1.0))
#define fi first
#define se second
#define SZ(x) ((int)x.size())
#define lson (o<<1),l,mid
#define rson (o<<1|1),mid+1,r
#define MP make_pair
#define sqr(x) ((x)*(x))
#define ALL(v) (v).begin(),(v).end()
#define showtime fprintf(stderr,"time = %.15f\n",clock() / (double)CLOCKS_PER_SEC)
const double eps = 1e-9 ;
const int MOD=(int)1e9+7,BAS=233;
inline int sign(double x){return x<-eps?-1:x>eps;}
inline int clz(int x){return __builtin_clz(x);}
inline int clz(ll x){return __builtin_clzll(x);}
inline int lg2(int x){return !x ? -1 : 31-clz(x);}
inline int lg2(ll x){return !x ? -1 : 63-clz(x);}
int AP (char *s) {
    unsigned hash=0;
    for(int i=0; s[i]; i++){
        if (i & 1) hash ^= (~((hash<<11)^s[i]^(hash>>5)));
        else hash ^= ((hash<<7)^s[i]^(hash>>3));
   } return hash & 0x7FFFFFFF;
}

const int M=2000000+10, nill=0;
int ls[M], rs[M], rt;
int b[M];

struct Node {
    int sz;
    unsigned fix;
    int v;
    int mk;
    void init (int _v) {
        v = _v;
        mk = 0;
    }
    void mark (int _mk) {
        mk += _mk;
        v += _mk;
    }
}T[M];

int MY;

struct Treap {
    inline unsigned ran () {
        static unsigned fix = 91250681;
        return fix += fix << 2 | 1;
    }
    inline int alloc (int _v) {
        T[MY].init(_v); T[MY].sz=1; T[MY].fix=ran(); ls[MY]=rs[MY]=nill;
        return MY++;
    }
    inline void down (int o) {
        if (T[o].mk == 0) return;
        T[ls[o]].mark (T[o].mk);
        T[rs[o]].mark (T[o].mk);
        T[o].mk = 0;
    }
    inline void up (int o) {
        T[o].sz = T[ls[o]].sz + T[rs[o]].sz + 1;
    }
    void cut (int o,int &a,int &b,int k) {
        if (T[o].sz<=k) {a=o,b=nill;return;}
        if (k<=0) {a=nill,b=o;return;}
        down (o);
        if (k>T[ls[o]].sz) cut (rs[o],rs[a=o],b,k-T[ls[o]].sz-1);
        else cut (ls[o],a,ls[b=o],k);
        up(o);
    }
    void Merge (int &o,int a,int b) {
        if (a==nill) o=b;
        else if (b==nill) o=a;
        else if (T[a].fix>T[b].fix) {
            down(a);
            Merge(rs[o=a],rs[a],b);
            up(o);
        } else {
            down(b);
            Merge(ls[o=b],a,ls[b]);
            up(o);
        }
    }
    int lower (int o,int v) {//求大于等于v的数的个数
        if (o == nill) return 0;
        down(o);
        if (T[o].v < v) {
            return lower (rs[o], v);
        } else {
            return 1 + T[rs[o]].sz + lower (ls[o], v);
        }
    }
    void build (int &o,int l,int r) {
        if (l > r) return;
        int mid = l + r>>1;
        o = alloc (b[mid]);
        build (ls[o], l, mid-1); build (rs[o], mid+1, r);
        up (o);
    }
    void del (int v) {//删除已经存在于集合中的数v
        int num = T[rt].sz - lower (rt, v);
        int a, b, c;
        cut (rt, a, b, num);
        cut (b, b, c, 1);
        Merge (rt, a, c);
    }
    void ins (int v) {
        int num = T[rt].sz - lower (rt, v);
        //printf ("num = %d\n", num);
        int a, b, c;
        cut (rt, a, b, num);
        c = alloc(v);
        Merge (rt, a, c);
        Merge (rt, rt, b);
        //printf ("ls:%d , rs:%d\n", T[ls[c]].v, T[rs[c]].v);
    }
    void update () {
        T[rt].mark(-1);
    }
    void Print (int o) {
        if (o==nill) return;
        down (o);
        //printf ("%d: %d, %d\n", T[o].v, T[ls[o]].v, T[rs[o]].v);
        //printf ("%d\n", T[o].sz);
        Print (ls[o]);
        printf ("%d ", T[o].v);
        Print (rs[o]);
    }
    void Clear () {
        rt = nill;
        T[rt].sz = 0; ls[rt] = rs[rt] = nill;
        MY = 1;
    }
} my;

int n;
int a[M];

int main () {
    //srand(time(0));
    my.Clear();
    scanf ("%d", &n);
    ll now = 0;
    for (int i=1; i<=n; ++i) {
        scanf ("%d", a+i);
        now += abs(a[i] - i);
        //my.ins(a[i] - i);
        b[i] = a[i] - i;
    }
    sort (b+1, b+1+n);
    my.build (rt, 1, n);
    ll minn = now;
    int k = 0;
    //printf ("%d: %I64d\n", 0, now);
    for (int i=n, j=0; i>=1 && j<300000; --i, ++j) {
        //my.Print(rt);
        now -= abs(a[i] - n);
        now += abs(a[i] - 1);
        my.del(a[i] - n);
        int f = my.lower (rt, 1);
        //printf ("f=%d, a[%d]=%d\n", f, i, a[i]);
        now += (T[rt].sz - f) - f;
        printf ("%d: %I64d\n", i, now);
        if (now < minn) {
            k = n-i+1;
            minn = now;
        }
        my.update();
        my.ins(a[i] - 1);
    }
    printf ("%I64d %d\n", minn, k);
    return 0;
}
/*
10
10 1 9 2 8 3 7 4 6 5
*/
treap

 

#include <bits/stdc++.h>
using namespace std;

const int N = 1e2 + 5;
const double EPS = 1e-10;
int sign(double x) {  //三态函数,减少精度问题
    return abs(x) < EPS ? 0 : x < 0 ? -1 : 1;
}
struct Point { //点的定义
    int x, y, id;
    Point(int x=0, int y=0) : x(x), y(y) {}
    Point operator + (const Point &rhs) const {  //向量加法
        return Point(x + rhs.x, y + rhs.y);
    }
    Point operator - (const Point &rhs) const {  //向量减法
        return Point(x - rhs.x, y - rhs.y);
    }
    Point operator * (int p) const {  //向量乘以标量
        return Point(x * p, y * p);
    }
    bool operator < (const Point &rhs) const {  //点的坐标排序
        return x < rhs.x || (x == rhs.x && y < rhs.y);
    }
    bool operator == (const Point &rhs) const {  //判断同一个点
        return x - rhs.x == 0 && y - rhs.y == 0;
    }
    void read() {
        scanf("%d%d", &x, &y);
    }
    void print() {
        printf("(%d, %d)\n", x, y);
    }
};
typedef Point Vector;  //向量的定义
typedef vector<Point> Polygon;  //多边形的定义。使用函数的前提:多边形poly排好序

int cross(Vector A, Vector B) {  //向量叉积,两向量组成的三角形的有向面积的两倍,可判断两向量的方向
    return A.x * B.y - A.y * B.x;
}

/*
 *凸包,基于水平序的Andrew算法。输入点的集合,返回凸包点的集合。
 *凸包边上无点:<=;凸包边上有点:<
 *时间复杂度O(NlogN)
 */
Polygon convex_hull(Polygon P) {
    sort(P.begin(), P.end());  //排序
    P.erase(unique(P.begin(), P.end()), P.end());  //删除重复点
    int n = P.size(), k = 0;
    Polygon Q(n*2);
    for (int i=0; i<n; ++i) {
        while (k > 1 && cross(Q[k-1]-Q[k-2], P[i]-Q[k-2]) < 0) k--;
        Q[k++] = P[i];
    }
    for (int t=k, i=n-2; i>=0; --i) {
        while (k > t && cross(Q[k-1]-Q[k-2], P[i]-Q[k-2]) < 0) k--;
        Q[k++] = P[i];
    }
    Q.resize(k-1);
    return Q;
}

Point p[N];
Polygon poly;
bool A[N];
int n;

int dot(Vector A, Vector B) {  //向量点积:向量长度的乘积再乘上夹角的余弦值,可判断两向量的角度
    return A.x * B.x + A.y * B.y;
}

double length(Vector A) {  //向量长度,点积
    return sqrt((double)dot(A, A));
}

bool spj() {
    if (n > 3) return false;
    Vector a = p[1] - p[0], b = p[2] - p[0];
    double x1 = a.x, y1 = a.y, x2 = b.x, y2 = b.y;
    double la = length(a), lb = length(b);
    x1 /= la; y1 /= la;
    x2 /= lb; y2 /= lb;
    return sign(x1-x2) == 0 && sign(y1-y2) == 0;
}

bool judge() {
    Polygon res = convex_hull(poly);
    int sz = res.size();
    if (sz == 3) {
        if (sz == n) {
            if (spj()) {  // 3 points in a line
                A[p[0].id] = A[p[2].id] = true; return true;
            } else return false;
        } else {
            A[res[0].id] = A[res[1].id] = A[res[2].id] = true; return true;
        }
    } else {
        A[res[0].id] = A[res[2].id] = true;
        return true;
    }
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        poly.clear();
        memset(A, false, sizeof(A[0])*(n+1));
        for (int i=0; i<n; ++i) {
            p[i].read();
            p[i].id = i;
            poly.push_back(p[i]);
        }
        sort(p, p+n);
        if (n < 3 || !judge()) puts("NO");
        else {
            puts("YES");
            for (int i=0; i<n; ++i) {
                if (A[i]) printf("%c", 'A');
                else printf("%c", 'B');
            }
            puts("");
        }
    }
    return 0;
}
凸包

 

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 15;
const int M = 362880;
typedef long long LL;
int n;
LL src, tim;
char str[N];
int s[N], s1[N], s2[N];
LL fac[N];
int vis[M];
queue <LL> que;
void cantor(int s[], LL num, int k){//康托展开,把一个数字num展开成一个数组s,k是数组长度
    int t;
    bool h[k];//0到k-1,表示是否出现过
    memset(h, 0, sizeof(h));
    for(int i = 0; i < k; i ++){
        t = num / fac[k-i-1];
        num = num % fac[k-i-1];
        for(int j = 0, pos = 0; ; j ++, pos ++){
            if(h[pos]) j --;
            if(j == t){
                h[pos] = true;
                s[i] = pos + 1;
                break;
            }
        }
    }
}
void inv_cantor(int s[], LL &num, int k){//康托逆展开,把一个数组s换算成一个数字num
    int cnt;
    num = 0;
    for(int i = 0; i < k; i ++){
        cnt = 0;
        for(int j = i + 1; j < k; j ++){
            if(s[i] > s[j]) cnt ++;//判断几个数小于它
        }
        num += fac[k-i-1] * cnt;
    }
}

int bfs(){
    if(src == tim) return 0;
    memset(vis, 0, sizeof(vis));
    while(!que.empty()) que.pop();
    que.push(src);
    que.push(0);
    vis[src] = 1;
    LL tmp, tmp2, dis;
    while(!que.empty()){
        tmp = que.front(); que.pop();
        dis = que.front(); que.pop();
        cantor(s, tmp, n);
        for(int i = 1; i < n; ++ i){
            swap(s[0], s[i]);
            inv_cantor(s, tmp2, n);
            swap(s[0], s[i]);
            if(vis[tmp2]) continue;
            if(tmp2 == tim) return dis+1;
            vis[tmp2] = 1;
            que.push(tmp2);
            que.push(dis+1);
        }
    }
}

int main(){
    fac[0] = 1;
    for(int i = 1; i < N; ++ i){
        fac[i] = fac[i-1] * i;
    }
    scanf("%d", &n);
    for(int cas = 1; cas <= 5; ++ cas){
        scanf("%s", str);
        for(int i = 0; i < n; ++ i){
            s[i] = str[i] - '1';
        }
        inv_cantor(s, src, n);
        scanf("%s", str);
        for(int i = 0; i < n; ++ i){
            s[i] = str[i] - '1';
        }
        inv_cantor(s, tim, n);
        
        int ans = bfs();
        printf("%d\n", ans);
    }
}
康托展开

 

ll solve(ll l,ll r) {
    while(r>l){
        ll m1=(2*l+r)/3;
        ll m2=(2*r+l+2)/3;
        ll ret1 = cal(m1);
        ll ret2 = cal(m2);
        //printf ("(%I64d, %I64d)\n", m1, ret1);
        //printf ("(%I64d, %I64d)\n", m2, ret2);
        if(ret1>ret2)
            r=m2-1;
        else
            l=m1+1;
    }
    return cal(l);
}
整型三分

 

#include<cstdio>
typedef long long LL;
int n;
LL dp[25];
void init(){
    dp[1] = 0;
    dp[2] = 1;
    for(int i = 3; i <= 20; i ++){
        dp[i] = (i-1) * (dp[i-1] + dp[i-2]);
    }
}
int main(){
    init();
    while(~scanf("%d", &n)){
        printf("%I64d\n", dp[n]);
    }
}
错排

 

const int block = 233;
struct Query {
    int l, r;
    int id;
    bool operator < (const Query &rhs) const {
        if (l/block == rhs.l/block) {
            return r < rhs.r;
        }
        return l < rhs.l;
    }
}qu[M];

void solve() {
    sort(qu, qu+m);
    l = r = nowAns = 0;
    for (int i = 0; i < m; ++i) {
        const Query &q = qu[i];
        while (l > q.l) Move(--l, 1);
        while (r < q.r) Move(++r, 1);
        while (l < q.l) Move(l++, -1);
        while (r > q.r) Move(r--, -1);
        ans[q.id] = nowAns;
    }
}
莫队

 

#include<bits/stdc++.h>
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = ((int)3e5 + 5)<<1;
char str[N];
int a[N];

struct Segtree {
    int T[N<<2];
    int up(int ls,int rs) {
        return min(ls, rs);
    }
    void build (int o,int l,int r) {
        if (l == r) {
            if (l & 1) T[o] = inf;
            else T[o] = l - (a[l]-1);
            //printf ("%d: %d\n", l, T[o]);
            return;
        }
        int mid = l+r>>1;
        build (lson); build(rson);
        T[o] = up(T[o<<1], T[o<<1|1]);
    }
    int ask (int o,int l,int r,int pl,int pr,int id) {
        if (pl<=l && r<=pr) {
            if (T[o] > id) {
                return -1;
            }
            if (l == r) return l;
        }
        int mid = l+r>>1;
        int ret = -1;
        if (pr>mid) ret = ask(rson,pl,pr,id);
        if (ret!=-1) return ret;
        if (pl<=mid) ret = ask(lson,pl,pr,id);
        return ret;
    }
}sgt;

char Ma[N];

int Manacher(char s[], int len, int ret[]){
    char sep = '#';
    for(int i = 0; i < len; i ++){
        Ma[i << 1] = sep;
        Ma[i << 1 | 1] = s[i];
    }
    Ma[len << 1] = sep;
    len = len << 1 | 1;
    int R = 0, id = 0, Max = 0;
    for(int i = 0; i < len; i ++){
        if(R > i) ret[i] = min(ret[2*id-i], R-i);
        else ret[i] = 1;
        while(i-ret[i] >= 0 && i+ret[i] < len && Ma[i-ret[i]] == Ma[i+ret[i]]) ret[i]++;
        if(i+ret[i] > R){
            R = i+ret[i];
            id = i;
        }
        Max = max(Max, ret[i]-1);
    }
    return Max;
}

int main(){
    int n, len;
    scanf("%d", &n);
    for(int i = 0; i < n; i ++){
        scanf("%s", str);
        len = strlen(str);
        Manacher(str, len, a);
        //printf("%d\n", Manacher(str, len, a));
        len = len<<1|1;
        /*for(int i = 0; i<len; i ++){
            printf("%d", a[i] - 1);
            printf(i == len-1 ? "\n" : " ");
        }*/
        sgt.build(1,0,len-1);
        int ans = 0;
        for (int i=2; i<len; i+=2) {
            int d = a[i]-1;
            int res = sgt.ask(1,0,len-1,i,i+d/2,i);
            //printf ("i=%d,(%d,%d)=%d\n", i, i, i+d/2, res);
            res = (res-i)>>1;
            ans = max(ans, res*4);
        }
        printf ("%d\n", ans);
    }
    return 0;
}
/*
5
aaaa
aa
abaabab
abrahellehhelleh
rachelhellabracadabra
*/
Manacher

 

#include<bits/stdc++.h>
typedef long long ll;
inline int clz(int x){return __builtin_clz(x);}
inline int clz(ll x){return __builtin_clzll(x);}
inline int lg2(int x){return !x ? -1 : 31-clz(x);}
inline int lg2(ll x){return !x ? -1 : 63-clz(x);}
using namespace std;
const int M = 200000+10, mod = (int)1e9+7;
int rk[M], sa[M], h[M], st[20][M];
int n, m;
char s[M];
char t[M];
int dp[M][32];
int x;

void da (char *s,int n,int m) {
    static int t1[M], t2[M], c[M];
    int *x=t1, *y=t2, i,j,k,p=1;
    memset (c, 0, sizeof(c[0])*m);
    for (i=0; i<n; i++) c[x[i]=s[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 (k=1; p<n; k<<=1, m=p) {
        for (p=0, i=n-k; i<n; i++) y[p++] = i;
        for (i=0; i<n; i++) if (sa[i]>=k) y[p++] = sa[i]-k;
        memset (c, 0, sizeof(c[0])*m);
        for (i=0; i<n; i++) c[x[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];
        for (swap(x,y), x[sa[0]]=0, p=i=1; i<n; i++)
            x[sa[i]] = y[sa[i]] == y[sa[i-1]] &&
                y[sa[i]+k] == y[sa[i-1]+k] ? p-1 : p++;
    }
    memcpy (rk, x, sizeof(x[0])*n);
    for (i=0, k=0; i<n-1; h[rk[i++]] = k?k--:k)
        for (j=sa[rk[i]-1]; s[i+k] == s[j+k]; k++);
    memcpy (st[0], h, sizeof(h[0])*n);
    for (k=1; 1<<k<=n; k++)
        for (i=0; i+(1<<k)-1<n; i++)
            st[k][i] = min (st[k-1][i], st[k-1][i+(1<<k-1)]);
}

int getlcp (int i,int j) {
    i = rk[i], j=rk[j];
    if (i>j) swap(i, j);
    i ++;
    int f = lg2 (j-i+1);
    return min (st[f][i], st[f][j-(1<<f)+1]);
}

int main () {
    scanf ("%d%s", &n, s);
    scanf ("%d%s", &m, t);
    scanf ("%d", &x);
    s[n] = '#';
    s[n+1] = 0;
    strcat (s, t);
    da (s, n+m+2, 128);
    memset (dp, -1, sizeof(dp));
    dp[0][0] = 0;
    for (int i=0; i<=n; ++i) {
        for (int j=0; j<=x; ++j) if (dp[i][j]!=-1) {
            dp[i+1][j] = max(dp[i+1][j], dp[i][j]);
            int lcp = getlcp (i, n+dp[i][j]+1);
            if (lcp == 0) continue;
            dp[i+lcp][j+1] = max(dp[i+lcp][j+1], dp[i][j] + lcp);
        }
    }
    for (int j=0; j<=x; ++j) {
        if (dp[n][j] == m) {
            puts ("YES");
            return 0;
        }
    }
    puts ("NO");
    return 0;
}
sa
posted @ 2017-07-30 10:24  92度的苍蓝  阅读(318)  评论(0编辑  收藏  举报
http://images.cnblogs.com/cnblogs_com/Running-Time/724426/o_b74124f376fc157f352acc88.jpg