Skip to content

Instantly share code, notes, and snippets.

@wowoto9772
Last active September 30, 2016 11:29
Show Gist options
  • Save wowoto9772/be328fb7efa25455b8ac444ce95e0757 to your computer and use it in GitHub Desktop.
Save wowoto9772/be328fb7efa25455b8ac444ce95e0757 to your computer and use it in GitHub Desktop.

2번 이상 등장하는 부분 문자열 중 길이가 가장 긴 것의 길이 (hashing)

const int h[] = { 40007, 1000003, 500009 };
int pwmd[26][200005][3]; // (i ^ j) % h[k]
char str[200003];
int n;
set < pair <int, int> > hsh[40007];
 
bool possible(int len) {
    for (int i = 0; i < 40007; i++)hsh[i].clear();
    int cur[] = { 0, 0, 0 };
    for (int j = 0; j < 3; j++) {
        for (int i = 0; i < len; i++) {
            cur[j] = (cur[j] * 26 + str[i]) % h[j];
        }
    }
    for (int i = len; i <= n; i++) {
        pair <int, int> cmpr = { cur[1], cur[2] };
        if (hsh[cur[0]].count(cmpr))return true;
        if (i == n)return false;
        hsh[cur[0]].emplace(cur[1], cur[2]);
        for (int j = 0; j < 3; j++) {
            cur[j] = (cur[j] * 26 + str[i]) % h[j];
            cur[j] = (cur[j] - pwmd[str[i - len]][len][j] + h[j]) % h[j];
        }
    }
 
    return false;
 
}
 
int main() {
 
    scanf("%d", &n);
 
    scanf("%s", str);
 
    for (int k = 0; k < 3; k++) {
        for (int i = 0; i < 26; i++) {
            pwmd[i][0][k] = i;
            for (int j = 1; j <= n; j++)pwmd[i][j][k] = (pwmd[i][j - 1][k] * 26) % h[k];
        }
 
    }
 
    for (int i = 0; i < n; i++) {
        str[i] = str[i] - 'a';
    }
 
    int l = 1, r = n - 1, m;
    int ans = 0;
 
    while (l <= r) {
        m = (l + r) / 2;
        if (possible(m)) {
            ans = max(ans, m);
            l = m + 1;
        }
        else {
            r = m - 1;
        }
    }
 
    printf("%d\n", ans);
 
}

Goldbach's congecture

Every even integer greater than 2 can be expressed as the sum of two primes.

Goldbach's weak congecture

Every odd number greater than 5 can be expressed as the sum of three primes

Euler trail, circuit

int adj[2003][2003];
int indegree[2003], outdegree[2003];
// 유향 그래프의 인접 행렬 adj 가 주어질 때 오일러 서킷을 계산한다. 
void getEulerCircuit(int here, vector<int>& circuit) {
    for (int there = 1; there <= N; ++there){
        while (adj[here][there] > 0) {
            adj[here][there]--; // 양쪽 간선을 모두 지운다
            getEulerCircuit(there, circuit);
        }
    }
    circuit.push_back(here);
}
 
// 현재 그래프의 오일러 트레일이나 서킷을 반환한다
vector<int> getEulerTrailOrCircuit() {
    vector<int> circuit;
    // 우선 트레일을 찾아본다: 시작점이 존재하는 경우
    for (int i = 1; i <= N; i++){
        if (outdegree[i] == indegree[i] + 1) {
            getEulerCircuit(i, circuit);
            return circuit;
        }
    }
    // 아니면 서킷이니, 간선에 인접한 아무 정점에서나 시작한다
    for (int i = 1; i <= N; i++){
        if (outdegree[i]) {
            getEulerCircuit(i, circuit);
            return circuit;
        }
    }
    // 모두 실패한 경우 빈 배열을 반환한다
    return circuit;
}
 
 
vector <int> solve() {
    vector<int> circuit = getEulerTrailOrCircuit();
    // 아닌 경우 방문 순서를 뒤집은 뒤 간선들을 모아 정답을 출력
    reverse(circuit.begin(), circuit.end());
    return circuit;
}

Euler formula

v − e + f = 2

tile dp (bottom up ver)

# Tile dp(bottom up)

```c++

int tileDP(){    
  // init
  int dp[H*W + 1][1 << W];
  for (int i = 0; i <= h*w; i++)
    for (int j = 0; j < (1 << w); j++)
      dp[i][j] = 0;
  dp[0][0] = 1;
  // DP
  for (int x = 0; x < h*w; x++) {
    for (int i = 0; i < (1 << w); i++) {
      if (i & 1) {
        dp[x + 1][i >> 1] += dp[x][i];
        dp[x + 1][i >> 1] %= mod;
      } else {
        if (!(i&3) && (x%w) != (w-1)) {
          dp[x + 1][(i >> 1) + 1] += dp[x][i];
          dp[x + 1][(i >> 1) + 1] %= mod;
        }
        dp[x + 1][(i >> 1) | (1 << (w - 1))] += dp[x][i];
        dp[x + 1][(i >> 1) | (1 << (w - 1))] %= mod;
      }
    }
  }
  // ANS
  return dp[w*h][0] % mod;
}

tile dp (top down ver)

int h, w;
long long dp[1 << 11][13][13];
long long dy(int n, int i, int j){
    if (i >= h)return 1;
    if (j >= w){
        return dy(n, i + 1, 0);
    }
    if (dp[n][i][j] != -1)return dp[n][i][j];
 
    dp[n][i][j] = 0;
 
    int n_ = (n >> 1);
    if (n & 1){
        return dp[n][i][j] = dy(n_, i, j + 1);
    }
 
    if (i < h - 1){
        dp[n][i][j] += dy(n_ | (1 << (w - 1)), i, j + 1);
    }
 
    if (j < w - 1 && !(n_ & 1)){
        n_ = n >> 2;
        dp[n][i][j] += dy(n_, i, j + 2);
    }
 
    return dp[n][i][j];
}
@nona1314
Copy link

Tile dp(bottom up)

int tileDP(){    
  // init
  int dp[H*W + 1][1 << W];
  for (int i = 0; i <= h*w; i++)
    for (int j = 0; j < (1 << w); j++)
      dp[i][j] = 0;
  dp[0][0] = 1;
  // DP
  for (int x = 0; x < h*w; x++) {
    for (int i = 0; i < (1 << w); i++) {
      if (i & 1) {
        dp[x + 1][i >> 1] += dp[x][i];
        dp[x + 1][i >> 1] %= mod;
      } else {
        if (!(i&3) && (x%w) != (w-1)) {
          dp[x + 1][(i >> 1) + 1] += dp[x][i];
          dp[x + 1][(i >> 1) + 1] %= mod;
        }
        dp[x + 1][(i >> 1) | (1 << (w - 1))] += dp[x][i];
        dp[x + 1][(i >> 1) | (1 << (w - 1))] %= mod;
      }
    }
  }
  // ANS
  return dp[w*h][0] % mod;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment