#include<bits/stdc++.h>
using namespace std;
 
template<typename T1, typename T2> istream& operator>>(istream& is, pair<T1,T2>& a){ return is >> a.first >> a.second; }
template<typename T1, typename T2> ostream& operator<<(ostream& os, pair<T1,T2>& a){ return os << a.first << " " << a.second; }
template<typename T> istream& operator>>(istream& is, vector< T >& vc){ for(int i = 0; i < vc.size(); i++) is >> vc[i]; return is; }
template<typename T> ostream& operator<<(ostream& os, vector< T >& vc){ for(int i = 0; i < vc.size(); i++) os << vc[i] << endl; return os; }
 
#define ForEach(it,c) for(__typeof (c).begin() it = (c).begin(); it != (c).end(); it++)
#define ALL(v) (v).begin(), (v).end()
#define UNQ(s) { sort(ALL(s)); (s).erase( unique( ALL(s)), (s).end());}

typedef pair< int , int > Pi;
typedef pair< int , Pi > Pii;
typedef long long int64;

int sum[1000000][3];
int sum2[1000000][3];

int main(){
  string str;
  cin >> str;

  for(int i = 0; i < str.size(); i++){
    int pos = string("JOI").find(str[i]);
    if(i) sum[i][pos] = sum[i - 1][pos] + 1;
    else sum[i][pos] = 1;
  }
  for(int i = str.size() - 1; i >= 0; i--){
    int pos = string("JOI").find(str[i]);
    if(i == str.size() - 1) sum2[i][pos] = 1;
    else sum2[i][pos] = sum2[i + 1][pos] + 1;
  }
  

  int ret = 0;
  for(int i = 1; i < str.size() - 1; i++){
    if(sum[i][1] > 0){ // 真ん中'O'の長さに依存してそう( こうさつ
      int J_pos = i - sum[i][1]; //これが'J'の終わり
      int I_pos = i + 1; // これが'I'の始まり
      if(J_pos >= 0 && (sum[J_pos][0] >= sum[i][1] && sum2[I_pos][2] >= sum[i][1])) ret = max( ret, min( sum[i][1], min( sum[J_pos][0], sum2[I_pos][2])));
    }
  }
  cout << ret << endl;
}
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <stack>
#include <vector>
#include <math.h>
#include <queue>

using namespace std;

struct Info{
	int succeed_num;
};

int main(){

	char* buf = new char[1000001];
	char pre;
	Info J_data,O_data;
	J_data.succeed_num = O_data.succeed_num = 0;

	scanf("%s",buf);

	int index,tmp,max_level;

	for(index = 0; buf[index] != 'J' && buf[index] != '\0';index++);

	pre = buf[index];

	if(pre == '\0'){
		printf("0\n");
		return 0;
	}

	max_level = 0;
	tmp = 0;
	for(;buf[index] != '\0';){
		if(pre == buf[index]){
			tmp++;

			if(buf[index+1] == '\0'){
				if(pre == 'I' && O_data.succeed_num <= J_data.succeed_num && O_data.succeed_num <= tmp){
					max_level = max(max_level,O_data.succeed_num);
				}
			}
			index++;
		}else{
			switch(pre){
			case 'J':
				if(buf[index] == 'O'){
					J_data.succeed_num = tmp;
					O_data.succeed_num = 0;
					pre = 'O';
				}else{
					for(;buf[index] != 'J' && buf[index] != '\0';index++);
					J_data.succeed_num = 0;
					O_data.succeed_num = 0;
					pre = 'J';
				}
				break;
			case 'O':
				if(buf[index] == 'I'){
					O_data.succeed_num = tmp;
					pre = 'I';
				}else{
					O_data.succeed_num = 0;
					pre = 'J';
				}
				break;
			case 'I':

				if(O_data.succeed_num <= J_data.succeed_num && O_data.succeed_num <= tmp){
					max_level = max(max_level,O_data.succeed_num);
				}
				J_data.succeed_num = 0;
				O_data.succeed_num = 0;

				if(buf[index] == 'J'){
					pre = 'J';
				}else{
					for(;buf[index] != 'J' && buf[index] != '\0';index++);
					pre = 'J';
				}
				break;
			}
			tmp = 0;
		}
	}

	printf("%d\n",max_level);

	return 0;
}